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 70 to Rev 71
- ↔ Reverse comparison
Rev 70 → Rev 71
/trunk/rtl/core/idecode.v
55,7 → 55,8
o_cond, o_wF, |
o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock, |
o_wR, o_rA, o_rB, |
o_early_branch, o_branch_pc |
o_early_branch, o_branch_pc, |
o_pipe |
); |
parameter ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1, |
IMPLEMENT_DIVIDE=1, IMPLEMENT_FPU=0, AW = ADDRESS_WIDTH; |
78,6 → 79,7
output reg o_wR, o_rA, o_rB; |
output wire o_early_branch; |
output wire [(AW-1):0] o_branch_pc; |
output reg o_pipe; |
|
wire dcdA_stall, dcdB_stall, dcdF_stall; |
wire o_dcd_early_branch; |
230,24 → 232,17
`endif |
|
|
initial o_illegal = 1'b0; |
always @(posedge i_clk) |
if (i_ce) |
if (i_rst) |
o_illegal <= 1'b0; |
else if (i_ce) |
begin |
`ifdef OPT_VLIW |
if (~o_phase) |
begin |
o_gie<= i_gie; |
// i.e. dcd_pc+1 |
o_pc <= i_pc+{{(AW-1){1'b0}},1'b1}; |
end |
|
o_illegal <= (i_illegal); |
o_illegal <= (i_illegal); |
`else |
o_illegal <= ((i_illegal) || (i_instruction[31])); |
o_gie<= i_gie; |
o_pc <= i_pc+{{(AW-1){1'b0}},1'b1}; |
`endif |
|
if ((IMPLEMENT_MPY!=1)&&(w_op[4:1]==4'h5)) |
o_illegal <= 1'b1; |
|
262,6 → 257,30
else if ((IMPLEMENT_FPU==0)&&(w_dcdFP)) |
o_illegal <= 1'b1; |
|
if ((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7) |
&&( |
(w_op[2:0] != 3'h2) // LOCK |
&&(w_op[2:0] != 3'h1) // BREAK |
&&(w_op[2:0] != 3'h0))) // NOOP |
o_illegal <= 1'b1; |
end |
|
|
always @(posedge i_clk) |
if (i_ce) |
begin |
`ifdef OPT_VLIW |
if (~o_phase) |
begin |
o_gie<= i_gie; |
// i.e. dcd_pc+1 |
o_pc <= i_pc+{{(AW-1){1'b0}},1'b1}; |
end |
`else |
o_gie<= i_gie; |
o_pc <= i_pc+{{(AW-1){1'b0}},1'b1}; |
`endif |
|
// Under what condition will we execute this |
// instruction? Only the load immediate instruction |
// is completely unconditional. |
301,10 → 320,6
|
o_break <= (w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)&&(w_op[2:0]==3'b001); |
o_lock <= (w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)&&(w_op[2:0]==3'b010); |
if ((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7) |
&&((w_op[2])||(w_op[1:0]==2'b11))) |
o_illegal <= 1'b1; |
|
`ifdef OPT_VLIW |
r_nxt_half <= { iword[31], iword[13:5], |
((iword[21])? iword[20:19] : 2'h0), |
354,6 → 369,37
assign o_branch_pc = {(AW){1'b0}}; |
end endgenerate |
|
|
// To be a pipeable operation there must be ... |
// 1. Two valid adjacent instructions |
// 2. Both must be memory operations, of the same time (both lods |
// or both stos) |
// 3. Both must use the same register base address |
// 4. Both must be to the same address, or the address incremented |
// by one |
// Note that we're not using iword here ... there's a lot of logic |
// taking place, and it's only valid if the new word is not compressed. |
// |
reg r_valid; |
always @(posedge i_clk) |
if (i_ce) |
o_pipe <= (r_valid)&&(i_pf_valid)&&(~i_instruction[31]) |
&&(w_dcdM)&&(o_M)&&(o_op[0] ==i_instruction[22]) |
&&(i_instruction[17:14] == o_dcdB[3:0]) |
&&(i_gie == o_gie) |
&&((i_instruction[21:19]==o_cond[2:0]) |
||(o_cond[2:0] == 3'h0)) |
&&((i_instruction[13:0]==r_I[13:0]) |
||({1'b0, i_instruction[13:0]}==(r_I[13:0]+14'h1))); |
always @(posedge i_clk) |
if (i_rst) |
r_valid <= 1'b0; |
else if ((i_ce)&&(i_pf_valid)) |
r_valid <= 1'b1; |
else if (~i_stalled) |
r_valid <= 1'b0; |
|
|
assign o_I = { {(32-22){r_I[22]}}, r_I[21:0] }; |
|
endmodule |
/trunk/rtl/core/idecode_deprecated.v
52,7 → 52,7
o_I, o_zI, o_cond, o_wF, o_op, |
o_ALU, o_M, o_DV, o_FP, o_break, o_lock, |
o_wR, o_rA, o_rB, |
o_early_branch, o_branch_pc |
o_early_branch, o_branch_pc, o_pipe |
); |
parameter ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1, |
IMPLEMENT_DIVIDE=0, IMPLEMENT_FPU=0, AW=ADDRESS_WIDTH; |
77,6 → 77,7
output reg o_wR, o_rA, o_rB; |
output wire o_early_branch; |
output wire [(AW-1):0] o_branch_pc; |
output wire o_pipe; |
|
|
assign o_phase = 1'b0; |
303,4 → 304,17
assign o_DV = 1'b0; |
assign o_FP = 1'b0; |
|
always @(posedge i_clk) |
if (i_ce) |
begin |
o_pipe <= (o_valid)&&(i_valid) |
&&(o_M)&&(w_op[3:1] == 3'h3)&&(w_op[0]==o_op[0]) |
&&(i_instruction[19:16] == o_B[3:0]) |
&&(i_gie == o_gie) |
&&((i_instruction[23:21]==o_cond) |
||(o_cond == 3'h0)) |
&&((i_instruction[15:0] == r_I[15:0]) |
||(i_instruction[15:0] == (r_I[15:0]+16'h1))); |
end |
|
endmodule |
/trunk/rtl/core/cpuops.v
33,7 → 33,7
/////////////////////////////////////////////////////////////////////////// |
// |
module cpuops(i_clk,i_rst, i_ce, i_valid, i_op, i_a, i_b, o_c, o_f, o_valid, |
o_illegal); |
o_illegal, o_busy); |
parameter IMPLEMENT_MPY = 1; |
input i_clk, i_rst, i_ce; |
input [3:0] i_op; |
43,6 → 43,7
output wire [3:0] o_f; |
output reg o_valid; |
output wire o_illegal; |
output wire o_busy; |
|
// Rotate-left pre-logic |
wire [63:0] w_rol_tmp; |
121,19 → 122,27
default: o_c <= i_b; // MOV, LDI |
endcase |
end |
|
assign o_busy = 1'b0; |
|
reg r_illegal; |
always @(posedge i_clk) |
r_illegal <= (i_ce)&&((i_op == 4'h3)||(i_op == 4'h4)); |
assign o_illegal = r_illegal; |
end else begin |
// |
// Multiply pre-logic |
// |
wire signed_mpy; |
assign signed_mpy = i_op[0]; |
wire signed [16:0] w_mpy_a_input, w_mpy_b_input; |
wire signed [33:0] w_mpy_result; |
assign w_mpy_a_input ={ ((i_a[15])&&(signed_mpy)), i_a[15:0] }; |
assign w_mpy_b_input ={ ((i_b[15])&&(signed_mpy)), i_b[15:0] }; |
assign w_mpy_result = w_mpy_a_input * w_mpy_b_input; |
wire [16:0] w_mpy_a_input, w_mpy_b_input; |
wire [33:0] w_mpy_result; |
reg [31:0] r_mpy_result; |
assign w_mpy_a_input ={ ((i_a[15])&(i_op[0])), i_a[15:0] }; |
assign w_mpy_b_input ={ ((i_b[15])&(i_op[0])), i_b[15:0] }; |
assign w_mpy_result = w_mpy_a_input * w_mpy_b_input; |
always @(posedge i_clk) |
if (i_ce) |
r_mpy_result = w_mpy_result[31:0]; |
|
|
// |
// The master ALU case statement |
// |
153,26 → 162,26
4'b0111:{o_c,c } <= w_asr_result[32:0]; // ASR |
4'b1000: o_c <= { i_b[15: 0], i_a[15:0] }; // LODIHI |
4'b1001: o_c <= { i_a[31:16], i_b[15:0] }; // LODILO |
4'b1010:{c,o_c } <= {1'b0,w_mpy_result[31:0]}; // MPYU |
4'b1011:{c,o_c } <= {1'b0,w_mpy_result[31:0]}; // MPYS |
4'b1010: o_c <= r_mpy_result; // MPYU |
4'b1011: o_c <= r_mpy_result; // MPYS |
4'b1100: o_c <= w_brev_result; // BREV |
4'b1101: o_c <= w_popc_result; // POPC |
4'b1110: o_c <= w_rol_result; // ROL |
default: o_c <= i_b; // MOV, LDI |
endcase |
end |
end endgenerate |
end else if (r_busy) |
o_c <= r_mpy_result; |
|
generate |
if (IMPLEMENT_MPY == 0) |
begin |
reg r_illegal; |
reg r_busy; |
initial r_busy = 1'b0; |
always @(posedge i_clk) |
r_illegal <= (i_ce)&&((i_op == 4'h3)||(i_op == 4'h4)); |
assign o_illegal = r_illegal; |
end else |
r_busy <= (~i_rst)&&(i_ce)&&(i_valid) |
&&(i_op[3:1] == 3'h5); |
|
assign o_busy = r_busy; |
|
assign o_illegal = 1'b0; |
endgenerate |
end endgenerate |
|
assign z = (o_c == 32'h0000); |
assign n = (o_c[31]); |
185,5 → 194,6
if (i_rst) |
o_valid <= 1'b0; |
else |
o_valid <= (i_ce)&&(i_valid); |
o_valid <= (i_ce)&&(i_valid)&&(i_op[3:1] != 3'h5) |
||(o_busy); |
endmodule |
/trunk/rtl/core/pfcache.v
100,7 → 100,7
// anyway. |
initial lastpc = 0; |
always @(posedge i_clk) |
if ((r_v)||(i_clear_cache)||(i_new_pc)) |
if (((r_v)&&(i_stall_n))||(i_clear_cache)||(i_new_pc)) |
lastpc <= i_pc; |
|
initial lasttag = 0; |
120,12 → 120,12
initial delay = 2'h3; |
initial r_v = 1'b0; |
always @(posedge i_clk) |
if ((i_rst)||(i_clear_cache)||(i_new_pc)||(r_v)) |
if ((i_rst)||(i_clear_cache)||(i_new_pc)||((r_v)&&(i_stall_n))) |
begin |
r_v <= r_v_from_pc; |
delay <= 2'h2; |
end else begin |
r_v <= r_v_from_last; |
end else if (~r_v) begin // Otherwise, r_v was true and we were |
r_v <= r_v_from_last; // stalled, hence only if ~r_v |
if (o_wb_cyc) |
delay <= 2'h2; |
else if (delay != 0) |
166,7 → 166,8
|
end else if ((~r_v)&&(delay==0) |
&&((tagval != lastpc[(AW-1):CW]) |
||(~vmask[lastpc[(CW-1):PW]]))) |
||(~vmask[lastpc[(CW-1):PW]])) |
&&(~o_illegal)) |
begin |
o_wb_cyc <= 1'b1; |
o_wb_stb <= 1'b1; |
189,16 → 190,27
else if ((o_wb_cyc)&&(i_wb_ack)&&(rdaddr[(PW-1):0] == {(PW){1'b1}})) |
vmask[rdaddr[(CW-1):PW]] <= 1'b1; |
|
reg illegal_valid; |
initial illegal_cache = 0; |
initial illegal_valid = 0; |
always @(posedge i_clk) |
if ((i_rst)||(i_clear_cache)) |
begin |
illegal_cache <= 0; |
else if ((o_wb_cyc)&&(i_wb_err)) |
illegal_valid <= 0; |
end else if ((o_wb_cyc)&&(i_wb_err)) |
begin |
illegal_cache <= lastpc[(AW-1):PW]; |
illegal_valid <= 1'b1; |
end |
|
initial o_illegal = 1'b0; |
always @(posedge i_clk) |
if (i_stall_n) |
o_illegal <= (illegal_cache == lastpc[(AW-1):PW]); |
if ((i_rst)||(i_clear_cache)) |
o_illegal <= 1'b0; |
else |
o_illegal <= (illegal_valid) |
&&(tagval == i_pc[(AW-1):CW]) |
&&(illegal_cache == i_pc[(AW-1):PW]); |
|
endmodule |
/trunk/rtl/core/zipcpu.v
141,7 → 141,16
`else |
parameter IMPLEMENT_MPY = 0; |
`endif |
parameter IMPLEMENT_DIVIDE = 1, IMPLEMENT_FPU = 0, |
`ifdef OPT_DIVIDE |
parameter IMPLEMENT_DIVIDE = 1; |
`else |
parameter IMPLEMENT_DIVIDE = 0; |
`endif |
`ifdef OPT_IMPLEMENT_FPU |
parameter IMPLEMENT_FPU = 1, |
`else |
parameter IMPLEMENT_FPU = 0, |
`endif |
IMPLEMENT_LOCK=1; |
`ifdef OPT_EARLY_BRANCHING |
parameter EARLY_BRANCHING = 1; |
242,7 → 251,8
wire [3:0] dcdF; |
wire dcdR_wr, dcdA_rd, dcdB_rd, |
dcdALU, dcdM, dcdDV, dcdFP, |
dcdF_wr, dcd_gie, dcd_break, dcd_lock; |
dcdF_wr, dcd_gie, dcd_break, dcd_lock, |
dcd_pipe; |
reg r_dcdvalid; |
wire dcdvalid; |
wire [(AW-1):0] dcd_pc; |
300,7 → 310,7
wire alu_ce, alu_stall; |
wire [31:0] alu_result; |
wire [3:0] alu_flags; |
wire alu_valid; |
wire alu_valid, alu_busy; |
wire set_cond; |
reg alu_wr, alF_wr, alu_gie; |
wire alu_illegal_op; |
319,7 → 329,6
wire mem_busy, mem_rdbusy; |
wire [(AW-1):0] mem_addr; |
wire [31:0] mem_data, mem_result; |
reg [4:0] mem_last_reg; // Last register result to go in |
|
wire div_ce, div_error, div_busy, div_valid; |
wire [31:0] div_result; |
407,14 → 416,12
// that cannot be pipelined, and the memory is |
// already busy |
||((opvalid_mem)&&(mem_stalled)) |
// ||((opvalid_mem)&&(dcdvalid)&&(dcdM)&&(~dcd_pipe)) |
) |
||(dcdvalid)&&( |
// Stall if we've got a read going with an |
// unknown output (known w/in the memory module) |
(mem_rdbusy) |
// Or if we need to wait for an operand A |
// Stall if we need to wait for an operand A |
// to be ready to read |
||(dcdA_stall) |
(dcdA_stall) |
// Likewise for B, also includes logic |
// regarding immediate offset (register must |
// be in register file if we need to add to |
424,10 → 431,10
// CC register |
||(dcdF_stall) |
); |
assign op_ce = (dcdvalid)&&((~opvalid)||(~op_stall))&&(~clear_pipeline); |
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline); |
`else |
assign op_stall = (opvalid)&&(~master_ce); |
assign op_ce = (dcdvalid); |
assign op_ce = ((dcdvalid)||(dcd_illegal)); |
`endif |
|
// |
444,7 → 451,7
// through the ALU. Break instructions are not allowed through |
// the ALU. |
`ifdef OPT_PIPELINED |
assign alu_stall = (((~master_ce)||(mem_rdbusy))&&(opvalid_alu)) //Case 1&2 |
assign alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2 |
// Old case #3--this isn't an ALU stall though ... |
||((opvalid_alu)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie) |
&&(wr_write_cc)) // Case 3 |
451,13 → 458,13
||((opvalid)&&(op_lock)&&(op_lock_stall)) |
||((opvalid)&&(op_break)) |
||(div_busy)||(fpu_busy); |
assign alu_ce = (master_ce)&&(opvalid_alu) |
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal)) |
&&(~alu_stall) |
&&(~clear_pipeline); |
`else |
assign alu_stall = ((~master_ce)&&(opvalid_alu)) |
||((opvalid_alu)&&(op_break)); |
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall); |
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall); |
`endif |
// |
|
467,16 → 474,15
// |
`ifdef OPT_PIPELINED |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled) |
&&(~clear_pipeline)&&(set_cond); |
&&(~clear_pipeline); |
`else |
// 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) |
&&(set_cond)&&(~mem_stalled); |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled); |
`endif |
`ifdef OPT_PIPELINED_BUS_ACCESS |
assign mem_stalled = (~master_ce)||((opvalid_mem)&&( |
assign mem_stalled = (~master_ce)||(alu_busy)||((opvalid_mem)&&( |
(mem_pipe_stalled) |
||((~op_pipe)&&(mem_busy)) |
||(div_busy) |
585,7 → 591,8
dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock, |
dcdR_wr,dcdA_rd, dcdB_rd, |
dcd_early_branch, |
dcd_branch_pc); |
dcd_branch_pc, |
dcd_pipe); |
`else |
idecode_deprecated |
#(AW, IMPLEMENT_MPY, EARLY_BRANCHING, IMPLEMENT_DIVIDE, |
601,12 → 608,11
dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock, |
dcdR_wr,dcdA_rd, dcdB_rd, |
dcd_early_branch, |
dcd_branch_pc); |
dcd_branch_pc, |
dcd_pipe); |
`endif |
|
`ifdef OPT_PIPELINED_BUS_ACCESS |
reg [23:0] r_opI; |
reg [4:0] op_B; |
reg op_pipe; |
|
initial op_pipe = 1'b0; |
616,20 → 622,12
// Both must be writes, or both must be reads |
// Both operations must be to the same identical address, |
// or at least a single (one) increment above that address |
// |
// However ... we need to know this before this clock, hence this is |
// calculated in the instruction decoder. |
always @(posedge i_clk) |
if (op_ce) |
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 |
&&((dcdI[23:0] == r_opI)||(dcdI[23:0]==r_opI+24'h1)); |
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
r_opI <= dcdI[23:0]; |
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
op_B <= dcdB; |
op_pipe <= dcd_pipe; |
`endif |
|
// |
647,7 → 645,21
else |
assign w_pcA_v = (dcdA[4] == dcd_gie)?dcd_pc:upc; |
endgenerate |
|
`ifdef OPT_PIPELINED |
reg [4:0] opA_id, opB_id; |
reg opA_rd, opB_rd; |
always @(posedge i_clk) |
if (op_ce) |
begin |
opA_id <= dcdA; |
opB_id <= dcdB; |
opA_rd <= dcdA_rd; |
opB_rd <= dcdB_rd; |
end |
`endif |
|
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
begin |
if ((wr_reg_ce)&&(wr_reg_id == dcdA)) |
659,11 → 671,13
else |
r_opA <= w_opA; |
`ifdef OPT_PIPELINED |
end else if (opvalid) |
end else |
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_wr))||((opA_mem)&&(mem_valid))) |
// r_opA <= wr_reg_vl; |
if ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd)) |
r_opA <= wr_reg_vl; |
`endif |
end |
686,9 → 700,7
if (op_ce) // &&(dcdvalid)) |
r_opB <= w_opBnI + dcdI; |
`ifdef OPT_PIPELINED |
else if ((opvalid)&&( |
((opB_alu)&&(alu_wr)) |
||((opB_mem)&&(mem_valid)))) |
else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd)) |
r_opB <= wr_reg_vl; |
`endif |
|
827,8 → 839,11
`endif |
|
`ifdef OPT_ILLEGAL_INSTRUCTION |
initial op_illegal = 1'b0; |
always @(posedge i_clk) |
if(op_ce) |
if ((i_rst)||(clear_pipeline)) |
op_illegal <= 1'b0; |
else if(op_ce) |
`ifdef OPT_PIPELINED |
op_illegal <=(dcd_illegal)||((dcd_lock)&&(IMPLEMENT_LOCK == 0)); |
`else |
836,32 → 851,18
`endif |
`endif |
|
generate |
if (EARLY_BRANCHING > 0) |
begin |
always @(posedge i_clk) |
if (op_ce) |
begin |
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))&&(~dcd_early_branch); |
opR_wr <= (dcdR_wr)&&(~dcd_early_branch); |
op_wr_pc <= ((dcdR_wr)&&(dcdR_pc) |
&&(dcdR[4] == dcd_gie)) |
&&(~dcd_early_branch); |
end |
end else begin |
always @(posedge i_clk) |
if (op_ce) |
begin |
// Will we write the flags/CC Register with |
// our result? |
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr)); |
// Will we be writing our results into a |
// register? |
opR_wr <= dcdR_wr; |
op_wr_pc <= ((dcdR_wr)&&(dcdR_pc) |
&&(dcdR[4] == dcd_gie)); |
end |
end endgenerate |
// No generate on EARLY_BRANCHING here, since if EARLY_BRANCHING is not |
// set, dcd_early_branch will simply be a wire connected to zero and |
// this logic should just optimize. |
always @(posedge i_clk) |
if (op_ce) |
begin |
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))&&(~dcd_early_branch); |
opR_wr <= (dcdR_wr)&&(~dcd_early_branch); |
op_wr_pc <= ((dcdR_wr)&&(dcdR_pc) |
&&(dcdR[4] == dcd_gie)) |
&&(~dcd_early_branch); |
end |
|
always @(posedge i_clk) |
if (op_ce) |
906,29 → 907,8
// define this flag to something other than just plain zero, then |
// the stalls will already be in place. |
`ifdef OPT_PIPELINED |
initial opA_alu = 1'b0; |
always @(posedge i_clk) |
if (op_ce) |
opA_alu <= (opvalid_alu)&&(opR == dcdA)&&(opR_wr)&&(dcdA_rd); |
else if ((opvalid)&&(opA_alu)&&(alu_valid)) |
opA_alu <= 1'b0; |
initial opA_mem = 1'b0; |
always @(posedge i_clk) |
if (op_ce) |
opA_mem <= ((opvalid_mem)&&(opR == dcdA)&&(dcdA_rd)&&(~opn[0])) |
||((~opvalid)&&(mem_busy)&&(~mem_we) |
&&(mem_last_reg == dcdA)&&(dcdA_rd)); |
else if ((opvalid)&&(opA_mem)&&(mem_valid)) |
opA_mem <= 1'b0; |
`endif |
|
always @(posedge i_clk) |
if (mem_ce) |
mem_last_reg <= opR; |
`ifdef OPT_PIPELINED |
assign opA = ((opA_alu)&&(alu_wr)) ? alu_result |
: ( ((opA_mem)&&(mem_valid))?mem_result |
: r_opA ); |
assign opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd)) |
? wr_reg_vl : r_opA; |
`else |
assign opA = r_opA; |
`endif |
935,7 → 915,8
|
`ifdef OPT_PIPELINED |
assign dcdA_stall = (dcdvalid)&&(dcdA_rd)&&( |
((opvalid_alu)&&(opF_wr)&&(dcdA_cc))); |
((opvalid_alu)&&(opF_wr)&&(dcdA_cc)) |
); |
`else |
// There are no pipeline hazards, if we aren't pipelined |
assign dcdA_stall = 1'b0; |
942,20 → 923,8
`endif |
|
`ifdef OPT_PIPELINED |
always @(posedge i_clk) |
if (op_ce) |
opB_alu <= (opvalid_alu)&&(opR == dcdB)&&(opR_wr)&&(dcdB_rd)&&(dcd_zI); |
always @(posedge i_clk) |
if (op_ce) |
opB_mem <= (dcd_zI)&&(dcdB_rd)&&( |
((opvalid_mem)&&(opR == dcdB)&&(~opn[0])) |
||((~opvalid)&&(mem_busy)&&(~mem_we) |
&&(mem_last_reg == dcdB))); |
else if ((opvalid)&&(opB_mem)&&(mem_valid)) |
opB_mem <= 1'b0; |
assign opB = ((opB_alu)&&(alu_wr)) ? alu_result |
: ( ((opB_mem)&&(mem_valid))?mem_result |
: r_opB ); |
assign opB = ((wr_reg_ce)&&(wr_reg_id == opB_id)&&(opB_rd)) |
? wr_reg_vl: r_opB; |
`else |
assign opB = r_opB; |
`endif |
971,16 → 940,18
// operand. That'll get wiped in the |
// next operation anyway, so don't stall |
// here. |
((opvalid)&&(opR_wr)&&(opR == dcdB) |
&&(opR != { op_gie, `CPU_PC_REG} ) |
&&(~dcd_zI)) |
((~dcd_zI)&&(dcdB_rd)&&(opR == dcdB)&&(opR_wr) |
&&(opR != { op_gie, `CPU_PC_REG } ) |
&&((opvalid)||(mem_rdbusy) |
||(div_busy)||(fpu_busy))) |
// Stall on any write to the flags register, |
// if we're going to need the flags value for |
// opB. |
||((opvalid_alu)&&(opF_wr)&&(dcdB_cc)) |
// Stall on any ongoing memory operation that |
// will write to opB |
||((mem_busy)&&(~mem_we)&&(mem_last_reg==dcdB))); |
// will write to opB -- captured above |
// ||((mem_busy)&&(~mem_we)&&(mem_last_reg==dcdB)&&(~dcd_zI)) |
); |
`else |
// No stalls without pipelining, 'cause how can you have a pipeline |
// hazard without the pipeline? |
998,11 → 969,13
`ifdef OPT_NEW_INSTRUCTION_SET |
cpuops #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce, |
(opvalid_alu), opn, opA, opB, |
alu_result, alu_flags, alu_valid, alu_illegal_op); |
alu_result, alu_flags, alu_valid, alu_illegal_op, |
alu_busy); |
`else |
cpuops_deprecated #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce, |
(opvalid_alu), opn, opA, opB, |
alu_result, alu_flags, alu_valid, alu_illegal_op); |
assign alu_busy = 1'b0; |
`endif |
|
generate |
1054,7 → 1027,7
// alu_reg <= opR; |
alu_wr <= (opR_wr)&&(set_cond); |
alF_wr <= (opF_wr)&&(set_cond); |
end else begin |
end else if (~alu_busy) begin |
// These are strobe signals, so clear them if not |
// set for any particular clock |
alu_wr <= (i_halt)&&(i_dbg_we); |
1099,7 → 1072,9
reg r_alu_illegal; |
initial r_alu_illegal = 0; |
always @(posedge i_clk) |
if ((alu_ce)||(mem_ce)) |
if (clear_pipeline) |
r_alu_illegal <= 1'b0; |
else if ((alu_ce)||(mem_ce)) |
r_alu_illegal <= op_illegal; |
assign alu_illegal = (alu_illegal_op)||(r_alu_illegal); |
`endif |
1136,7 → 1111,7
`endif |
|
`ifdef OPT_PIPELINED_BUS_ACCESS |
pipemem #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst, mem_ce, bus_lock, |
pipemem #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst,(mem_ce)&&(set_cond), bus_lock, |
(opn[0]), opB, opA, opR, |
mem_busy, mem_pipe_stalled, |
mem_valid, bus_err, mem_wreg, mem_result, |
1146,7 → 1121,7
mem_ack, mem_stall, mem_err, i_wb_data); |
|
`else // PIPELINED_BUS_ACCESS |
memops #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst, mem_ce, bus_lock, |
memops #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst,(mem_ce)&&(set_cond), bus_lock, |
(opn[0]), opB, opA, opR, |
mem_busy, |
mem_valid, bus_err, mem_wreg, mem_result, |
1190,7 → 1165,7
// 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)||(div_valid)||(fpu_valid); |
assign wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid); |
`else |
assign wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid); |
`endif |
1205,10 → 1180,10
// 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_valid) ? mem_result |
:((div_valid) ? div_result |
:fpu_result)); |
assign wr_reg_vl = ((mem_valid) ? mem_result |
:((div_valid|fpu_valid)) |
? ((div_valid) ? div_result:fpu_result) |
:((dbgv) ? dbg_val : alu_result)); |
always @(posedge i_clk) |
if (wr_reg_ce) |
regset[wr_reg_id] <= wr_reg_vl; |
1218,8 → 1193,14
// When shall we write to our flags register? alF_wr already |
// includes the set condition ... |
assign wr_flags_ce = ((alF_wr)||(div_valid)||(fpu_valid))&&(~clear_pipeline)&&(~alu_illegal); |
assign w_uflags = { ufpu_err_flag, udiv_err_flag, ubus_err_flag, trap, ill_err_u, 1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags }; |
assign w_iflags = { ifpu_err_flag, idiv_err_flag, 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 = { ufpu_err_flag, |
udiv_err_flag, ubus_err_flag, trap, ill_err_u, |
1'b0, step, 1'b1, sleep, |
((wr_flags_ce)&&(alu_gie))?alu_flags:flags }; |
assign w_iflags = { ifpu_err_flag, |
idiv_err_flag, ibus_err_flag, trap, ill_err_i, |
break_en, 1'b0, 1'b0, sleep, |
((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags }; |
|
|
// What value to write? |
1268,7 → 1249,7
||((~alu_gie)&&(bus_err)) |
||((~alu_gie)&&(div_valid)&&(div_error)) |
||((~alu_gie)&&(fpu_valid)&&(fpu_error)) |
||((~alu_gie)&&(alu_valid)&&(alu_illegal)); |
||((~alu_gie)&&(alu_pc_valid)&&(alu_illegal)); |
`else |
assign o_break = (((break_en)||(~op_gie))&&(op_break) |
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy) |
1324,10 → 1305,15
&&(op_break)&&(~break_en)) |
`ifdef OPT_ILLEGAL_INSTRUCTION |
// On an illegal instruction |
||((alu_valid)&&(alu_illegal)) |
||((alu_pc_valid)&&(alu_illegal)) |
`endif |
||((div_valid)&&(div_error)) |
||((fpu_valid)&&(fpu_error)) |
// On division by zero. If the divide isn't |
// implemented, div_valid and div_error will be short |
// circuited and that logic will be bypassed |
||((div_valid)&&(div_error)) |
// Same thing on a floating point error. |
||((fpu_valid)&&(fpu_error)) |
// |
||(bus_err) |
// If we write to the CC register |
||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT]) |
1365,7 → 1351,7
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)) |
else if ((alu_pc_valid)&&(alu_illegal)&&(~alu_gie)) |
ill_err_i <= 1'b1; |
initial ill_err_u = 1'b0; |
always @(posedge i_clk) |
1380,7 → 1366,7
&&(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)) |
else if ((alu_pc_valid)&&(alu_illegal)&&(alu_gie)) |
ill_err_u <= 1'b1; |
`else |
assign ill_err_u = 1'b0; |
1614,7 → 1600,7
// later evaluate how well we are doing. |
// |
// |
assign o_op_stall = (master_ce)&&((~opvalid)||(op_stall)); |
assign o_op_stall = (master_ce)&&(op_stall); |
assign o_pf_stall = (master_ce)&&(~pf_valid); |
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline); |
|
1621,7 → 1607,6
`ifdef DEBUG_SCOPE |
always @(posedge i_clk) |
o_debug <= { |
/* |
pf_pc[3:0], flags, |
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid, |
op_ce, alu_ce, mem_ce, |
1635,8 → 1620,8
// ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled))); |
// opA[23:20], opA[3:0], |
gie, sleep, |
wr_reg_vl[5:0] |
*/ |
wr_reg_ce, wr_reg_vl[4:0] |
/* |
i_rst, master_ce, (new_pc), |
((dcd_early_branch)&&(dcdvalid)), |
pf_valid, pf_illegal, |
1643,6 → 1628,7
op_ce, dcd_ce, dcdvalid, dcd_stalled, |
pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err, |
pf_pc[7:0], pf_addr[7:0] |
*/ |
}; |
`endif |
|
/trunk/rtl/zipsystem.v
183,9 → 183,9
IMPLEMENT_DIVIDE=0, |
`endif |
`ifdef OPT_IMPLEMENT_FPU |
IMPLEMENT_FPU=1, |
`else |
IMPLEMENT_FPU=0, |
`else |
IMPLEMENT_FPU=1, |
`endif |
IMPLEMENT_LOCK=1, |
// Derived parameters |
510,8 → 510,6
assign actr_stall = 1'b0; |
assign actr_data = 32'h0000; |
|
wire utc_int, uoc_int, upc_int, uic_int; |
wire mtc_int, moc_int, mpc_int, mic_int; |
assign mtc_int = 1'b0; |
assign moc_int = 1'b0; |
assign mpc_int = 1'b0; |
572,18 → 570,17
assign dmac_int = 1'b0; |
`endif |
|
wire ctri_sel; |
reg ctri_ack; |
wire ctri_sel, ctri_stall; |
reg ctri_ack; |
wire [31:0] ctri_data; |
assign ctri_sel = (sys_cyc)&&(sys_stb)&&(sys_addr == `CTRINT); |
always @(posedge i_clk) |
ctri_ack <= ctri_sel; |
assign ctri_stall = 1'b0; |
`ifdef INCLUDE_ACCOUNTING_COUNTERS |
// |
// Counter Interrupt controller |
// |
wire ctri_stall; |
wire [31:0] ctri_data; |
|
generate |
if (EXTERNAL_INTERRUPTS <= 9) |
begin |
598,14 → 595,11
ctri_int); |
end endgenerate |
|
assign ctri_stall = 1'b0; |
`else // INCLUDE_ACCOUNTING_COUNTERS |
|
generate |
if (EXTERNAL_INTERRUPTS <= 9) |
begin |
wire ctri_stall, ctri_int; |
wire [31:0] ctri_data; |
assign ctri_stall = 1'b0; |
assign ctri_data = 32'h0000; |
assign ctri_int = 1'b0; |
/trunk/rtl/cpudefs.v
267,6 → 267,5
// |
// |
// `define DEBUG_SCOPE |
`define NEW_PREFETCH_VERSION |
// |
`endif // CPUDEFS_H |