URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk/rtl/core
- from Rev 36 to Rev 38
- ↔ Reverse comparison
Rev 36 → Rev 38
/pipemem.v
0,0 → 1,146
/////////////////////////////////////////////////////////////////////////// |
// |
// Filename: pipemem.v |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
// Purpose: A memory unit to support a CPU, this time one supporting |
// pipelined wishbone memory accesses. The goal is to be able |
// to issue one pipelined wishbone access per clock, and (given the memory |
// is fast enough) to be able to read the results back at one access per |
// clock. This renders on-chip memory fast enough to handle single cycle |
// (pipelined) access. |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Tecnology, LLC |
// |
/////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
// |
module pipemem(i_clk, i_rst, i_pipe_stb, |
i_op, i_addr, i_data, i_oreg, |
o_busy, o_pipe_stalled, o_valid, o_err, o_wreg, o_result, |
o_wb_cyc_gbl, o_wb_cyc_lcl, |
o_wb_stb_gbl, o_wb_stb_lcl, |
o_wb_we, o_wb_addr, o_wb_data, |
i_wb_ack, i_wb_stall, i_wb_err, i_wb_data); |
input i_clk, i_rst; |
input i_pipe_stb; |
// CPU interface |
input i_op; |
input [31:0] i_addr; |
input [31:0] i_data; |
input [4:0] i_oreg; |
// CPU outputs |
output wire o_busy; |
output wire o_pipe_stalled; |
output reg o_valid; |
output reg o_err; |
output reg [4:0] o_wreg; |
output reg [31:0] o_result; |
// Wishbone outputs |
output reg o_wb_cyc_gbl, o_wb_stb_gbl; |
output reg o_wb_cyc_lcl, o_wb_stb_lcl, o_wb_we; |
output reg [31:0] o_wb_addr, o_wb_data; |
// Wishbone inputs |
input i_wb_ack, i_wb_stall, i_wb_err; |
input [31:0] i_wb_data; |
|
reg [3:0] rdaddr, wraddr; |
wire [3:0] nxt_rdaddr; |
reg [(5-1):0] fifo_oreg [0:15]; |
initial rdaddr = 0; |
initial wraddr = 0; |
always @(posedge i_clk) |
fifo_oreg[wraddr] <= i_oreg; |
always @(posedge i_clk) |
if ((i_rst)||(i_wb_err)) |
wraddr <= 0; |
else if (i_pipe_stb) |
wraddr <= wraddr + 1; |
always @(posedge i_clk) |
if ((i_rst)||(i_wb_err)) |
rdaddr <= 0; |
else if ((i_wb_ack)&&((o_wb_cyc_gbl)||(o_wb_cyc_lcl))) |
rdaddr <= rdaddr + 1; |
assign nxt_rdaddr = rdaddr + 1; |
|
wire gbl_stb, lcl_stb; |
assign lcl_stb = (i_addr[31:8]==24'hc00000)&&(i_addr[7:5]==3'h0); |
assign gbl_stb = ((i_addr[31:8]!=24'hc00000)||(i_addr[7:5]!=3'h0)); |
|
always @(posedge i_clk) |
if (i_rst) |
begin |
o_wb_cyc_gbl <= 1'b0; |
o_wb_cyc_lcl <= 1'b0; |
o_wb_stb_gbl <= 1'b0; |
o_wb_stb_lcl <= 1'b0; |
end else if ((o_wb_cyc_gbl)||(o_wb_cyc_lcl)) |
begin |
if ((~i_wb_stall)&&(~i_pipe_stb)) |
begin |
o_wb_stb_gbl <= 1'b0; |
o_wb_stb_lcl <= 1'b0; |
end else if ((i_pipe_stb)&&(~i_wb_stall)) |
begin |
o_wb_addr <= i_addr; |
o_wb_data <= i_data; |
end |
|
if (((i_wb_ack)&&(nxt_rdaddr == wraddr))||(i_wb_err)) |
begin |
o_wb_cyc_gbl <= 1'b0; |
o_wb_cyc_lcl <= 1'b0; |
end |
end else if (i_pipe_stb) // New memory operation |
begin // Grab the wishbone |
o_wb_cyc_lcl <= lcl_stb; |
o_wb_cyc_gbl <= gbl_stb; |
o_wb_stb_lcl <= lcl_stb; |
o_wb_stb_gbl <= gbl_stb; |
o_wb_addr <= i_addr; |
o_wb_data <= i_data; |
// o_wb_we <= i_op |
end |
always @(posedge i_clk) |
if ((i_pipe_stb) |
&&((~i_wb_stall) |
||((~o_wb_cyc_gbl)&&(~o_wb_cyc_lcl)))) |
o_wb_we <= i_op; |
|
initial o_valid = 1'b0; |
always @(posedge i_clk) |
o_valid <= ((o_wb_cyc_gbl)||(o_wb_cyc_lcl))&&(i_wb_ack)&&(~o_wb_we); |
initial o_err = 1'b0; |
always @(posedge i_clk) |
o_err <= ((o_wb_cyc_gbl)||(o_wb_cyc_lcl))&&(i_wb_err); |
assign o_busy = (o_wb_cyc_gbl)||(o_wb_cyc_lcl); |
|
always @(posedge i_clk) |
o_wreg <= fifo_oreg[rdaddr]; |
always @(posedge i_clk) |
if (i_wb_ack) |
o_result <= i_wb_data; |
|
assign o_pipe_stalled = ((o_wb_cyc_gbl)||(o_wb_cyc_lcl)) |
&&((i_wb_stall)||((~o_wb_stb_lcl)&&(~o_wb_stb_gbl))); |
endmodule |
/pipefetch.v
215,7 → 215,13
always @(posedge i_clk) |
if (i_clear_cache) |
o_wb_addr <= i_pc; |
else if ((~o_wb_cyc)&&((w_pc_out_of_bounds) |
else if ((o_wb_cyc)&&(w_pc_out_of_bounds)) |
begin |
if (i_wb_ack) |
o_wb_addr <= r_cache_base + bus_nvalid+1; |
else |
o_wb_addr <= r_cache_base + bus_nvalid; |
end else if ((~o_wb_cyc)&&((w_pc_out_of_bounds) |
||(w_ran_off_end_of_cache))) |
o_wb_addr <= (i_new_pc) ? i_pc : r_addr; |
else if ((o_wb_cyc)&&(o_wb_stb)&&(~i_wb_stall)) |
225,9 → 231,9
always @(posedge i_clk) |
if (~o_wb_cyc) |
r_acks_waiting <= 0; |
else if ((o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack)) |
else if ((o_wb_cyc)&&(o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack)) |
r_acks_waiting <= r_acks_waiting + 1; |
else if ((i_wb_ack)&&((~o_wb_stb)||(i_wb_stall))) |
else if ((o_wb_cyc)&&(i_wb_ack)&&((~o_wb_stb)||(i_wb_stall))) |
r_acks_waiting <= r_acks_waiting - 1; |
|
always @(posedge i_clk) |
/zipcpu.v
116,7 → 116,7
// Single Fetching 2521 1734 |
// Pipelined fetching 2796 2046 |
// |
// `define SINGLE_FETCH |
// `define OPT_SINGLE_FETCH |
// |
// |
// |
128,12 → 128,14
`define CPU_GIE_BIT 5 |
`define CPU_SLEEP_BIT 4 |
// Compile time defines |
// `define SINGLE_FETCH |
`define NG_CONDITIONAL_FLAGS |
`define NG_PRECLEAR_BUS // 0.61 w/ or w/o |
// `define NG_BRANCH_DELAY_SLOT |
`define NG_ILLEGAL_INSTRUCTION |
`define NG_EARLY_BRANCHING // 0.60 w/, 0.61 w/o ???? |
// (Currently unused) |
// `define OPT_SINGLE_FETCH |
// (Best path--define these!) |
`define OPT_CONDITIONAL_FLAGS |
`define OPT_PRECLEAR_BUS |
`define OPT_ILLEGAL_INSTRUCTION |
`define OPT_EARLY_BRANCHING |
`define OPT_PIPELINED_BUS_ACCESS |
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, |
147,7 → 149,7
i_wb_err, |
// Accounting/CPU usage interface |
o_op_stall, o_pf_stall, o_i_count); |
parameter RESET_ADDRESS=32'h0100000; |
parameter RESET_ADDRESS=32'h0100000, LGICACHE=9; |
input i_clk, i_rst, i_interrupt; |
// Debug interface -- inputs |
input i_halt, i_clear_pf_cache; |
180,8 → 182,10
reg [3:0] flags, iflags; // (TRAP,FPEN,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z |
wire [10:0] w_uflags, w_iflags; |
reg trap, break_en, step, gie, sleep; |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg ill_err; |
`else |
wire ill_err; |
`endif |
reg bus_err_flag; |
|
222,13 → 226,13
reg [23:0] r_dcdI; |
wire dcdA_stall, dcdB_stall, dcdF_stall; |
|
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
reg dcd_clear_bus; |
`endif |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg dcd_illegal; |
`endif |
`ifdef NG_EARLY_BRANCHING |
`ifdef OPT_EARLY_BRANCHING |
reg dcd_early_branch_stb, dcd_early_branch; |
reg [31:0] dcd_branch_pc; |
`else |
257,10 → 261,10
reg [6:0] r_opF; |
wire [8:0] opF; |
wire op_ce; |
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
reg op_clear_bus; |
`endif |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg op_illegal; |
`endif |
|
279,13 → 283,18
wire alu_valid; |
wire set_cond; |
reg alu_wr, alF_wr, alu_gie; |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg alu_illegal; |
`else |
wire alu_illegal; |
`endif |
|
|
|
wire mem_ce, mem_stalled; |
`ifdef OPT_PIPELINED_BUS_ACCESS |
wire mem_pipe_stalled; |
`endif |
wire mem_valid, mem_ack, mem_stall, mem_err, bus_err, |
mem_cyc_gbl, mem_cyc_lcl, mem_stb_gbl, mem_stb_lcl, mem_we; |
wire [4:0] mem_wreg; |
311,7 → 320,7
// |
// MASTER: clock enable. |
// |
assign master_ce = (~i_halt)&&(~o_break)&&(~sleep)&&(~mem_rdbusy); |
assign master_ce = (~i_halt)&&(~o_break)&&(~sleep); |
|
|
// |
325,9 → 334,7
assign dcd_stalled = (dcdvalid)&&( |
(op_stall) |
||((dcdA_stall)||(dcdB_stall)||(dcdF_stall)) |
`ifndef NG_BRANCH_DELAY_SLOT |
||((opvalid_mem)&&(op_wr_pc)) |
`endif |
||((opvalid_mem)&&(opR_cc))); |
// |
// PIPELINE STAGE #3 :: Read Operands |
350,17 → 357,26
// through the ALU. Break instructions are not allowed through |
// the ALU. |
assign alu_stall = (((~master_ce)||(mem_rdbusy))&&(opvalid_alu)) //Case 1&2 |
`ifdef BEFORE |
||((opvalid)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie) |
&&((wr_write_pc)||(wr_write_cc)) // Case 3 |
`else |
||((opvalid_mem)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie) |
&&((wr_write_pc)||(wr_write_cc))) // Case 3 |
`endif |
||((opvalid)&&(op_break)); // Case 4 |
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline); |
assign alu_ce = (master_ce)&&(~mem_rdbusy)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline); |
// |
`ifdef OPT_PIPELINED_BUS_ACCESS |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~clear_pipeline) |
&&(set_cond)&&(~mem_stalled); |
assign mem_stalled = (~master_ce)||((opvalid_mem)&&( |
(mem_pipe_stalled) |
||((~op_pipe)&&(mem_busy)) |
// Stall waiting for flags to be valid |
// Or waiting for a write to the PC register |
// Or CC register, since that can change the |
// PC as well |
||((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 |
368,6 → 384,7
// Or CC register, since that can change the |
// PC as well |
||((wr_reg_ce)&&(wr_reg_id[4] == op_gie)&&((wr_write_pc)||(wr_write_cc))))); |
`endif |
|
|
// |
375,7 → 392,7
// PIPELINE STAGE #1 :: Prefetch |
// |
// |
`ifdef SINGLE_FETCH |
`ifdef OPT_SINGLE_FETCH |
wire pf_ce; |
|
assign pf_ce = (~dcd_stalled); |
385,7 → 402,7
pf_cyc, pf_stb, pf_we, pf_addr, pf_data, |
pf_ack, pf_stall, pf_err, i_wb_data); |
`else // Pipe fetch |
pipefetch #(RESET_ADDRESS) |
pipefetch #(RESET_ADDRESS, LGICACHE) |
pf(i_clk, i_rst, (new_pc)|(dcd_early_branch_stb), |
i_clear_pf_cache, ~dcd_stalled, |
(new_pc)?pf_pc:dcd_branch_pc, |
392,7 → 409,7
instruction, instruction_pc, pf_valid, |
pf_cyc, pf_stb, pf_we, pf_addr, pf_data, |
pf_ack, pf_stall, pf_err, i_wb_data, |
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
((dcd_clear_bus)&&(dcdvalid)) |
||((op_clear_bus)&&(opvalid)) |
|| |
411,9 → 428,9
else if ((~dcd_stalled)||(clear_pipeline)||(dcd_early_branch)) |
dcdvalid <= 1'b0; |
|
`ifdef NG_EARLY_BRANCHING |
`ifdef OPT_EARLY_BRANCHING |
always @(posedge i_clk) |
if ((dcd_ce)&&(instruction[27:24]==`CPU_PC_REG)) |
if ((dcd_ce)&&(instruction[27:24]==`CPU_PC_REG)&&(~sleep)) |
begin |
dcd_early_branch <= 1'b0; |
// First case, a move to PC instruction |
456,11 → 473,11
else // if (instruction[28]) // 4'h3 = LDI |
dcd_branch_pc <= instruction_pc+32'h01+{ {(8){instruction[23]}}, instruction[23:0] }; |
end |
`else // NG_EARLY_BRANCHING |
`else // OPT_EARLY_BRANCHING |
assign dcd_early_branch_stb = 1'b0; |
assign dcd_early_branch = 1'b0; |
assign dcd_branch_pc = 32'h00; |
`endif // NG_EARLY_BRANCHING |
`endif // OPT_EARLY_BRANCHING |
|
always @(posedge i_clk) |
if (dcd_ce) |
478,15 → 495,15
dcdA_pc <= (instruction[27:24] == `CPU_PC_REG); |
dcdB_pc <= (instruction[19:16] == `CPU_PC_REG); |
dcdM <= 1'b0; |
`ifdef NG_CONDITIONAL_FLAGS |
`ifdef OPT_CONDITIONAL_FLAGS |
dcdF_wr <= (instruction[23:21]==3'h0); |
`else |
dcdF_wr <= 1'b1; |
`endif |
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
dcd_clear_bus <= 1'b0; |
`endif |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
dcd_illegal <= pf_illegal; |
`endif |
|
517,7 → 534,7
dcdOp <= 4'h2; |
end |
4'h4: begin // Multiply, LDI[HI|LO], or NOOP/BREAK |
`ifdef NG_CONDITIONAL_FLAGS |
`ifdef OPT_CONDITIONAL_FLAGS |
// Don't write flags except for multiplies |
// and then only if they are unconditional |
dcdF_wr <= ((instruction[27:25] != 3'h7) |
536,7 → 553,7
dcdOp <= 4'h2; |
// Might also be a break. Big |
// instruction set hole here. |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
dcd_illegal <= (pf_illegal)||(instruction[23:1] != 0); |
`endif |
end else if (instruction[27:24] == 4'hf) |
565,7 → 582,7
else |
r_dcdI <= { {(4){instruction[19]}}, instruction[19:0] }; |
dcdM <= 1'b1; // Memory operation |
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
dcd_clear_bus <= (instruction[23:21]==3'h0); |
`endif |
end |
586,10 → 603,35
always @(posedge i_clk) |
if (dcd_ce) |
dcd_break <= (instruction[31:0] == 32'h4e000001); |
else if ((clear_pipeline)||(~dcdvalid)) |
else if ((clear_pipeline)||(~dcdvalid)) // SHOULDNT THIS BE ||op_ce? |
dcd_break <= 1'b0; |
|
`ifdef OPT_PIPELINED_BUS_ACCESS |
reg [23:0] r_opI; |
reg [4:0] op_B; |
reg op_pipe; |
|
initial op_pipe = 1'b0; |
// To be a pipeable operation, there must be |
// two valid adjacent instructions |
// Both must be memory instructions |
// 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 |
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 |
&&((r_dcdI == r_opI)||(r_dcdI==r_opI+24'h1)); |
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
r_opI <= r_dcdI; |
always @(posedge i_clk) |
if (op_ce) // &&(dcdvalid)) |
op_B <= dcdB; |
`endif |
|
// |
// |
// PIPELINE STAGE #3 :: Read Operands (Registers) |
668,7 → 710,7
// wait until our operands are valid, then we aren't |
// valid yet until then. |
opvalid<= (~clear_pipeline)&&(dcdvalid)&&(~dcd_stalled); |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
opvalid_mem <= (dcdM)&&(~dcd_illegal)&&(~clear_pipeline)&&(dcdvalid)&&(~dcd_stalled); |
opvalid_alu <= ((~dcdM)||(dcd_illegal))&&(~clear_pipeline)&&(dcdvalid)&&(~dcd_stalled); |
`else |
698,7 → 740,7
else if ((clear_pipeline)||(~opvalid)) |
op_break <= 1'b0; |
|
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
always @(posedge i_clk) |
if(op_ce) |
op_illegal <= dcd_illegal; |
709,7 → 751,7
begin |
opn <= dcdOp; // Which ALU operation? |
// opM <= dcdM; // Is this a memory operation? |
`ifdef NG_EARLY_BRANCH |
`ifdef OPT_EARLY_BRANCHING |
opF_wr <= (dcdF_wr)&&((~dcdA_cc)||(~dcdA_wr))&&(~dcd_early_branch); |
opR_wr <= (dcdA_wr)&&(~dcd_early_branch); |
`else |
720,7 → 762,7
`endif |
// What register will these results be written into? |
opR <= dcdA; |
opR_cc <= (dcdA_wr)&&(dcdA_cc); |
opR_cc <= (dcdA_wr)&&(dcdA_cc)&&(dcdA[4]==dcd_gie); |
// User level (1), vs supervisor (0)/interrupts disabled |
op_gie <= dcd_gie; |
|
733,13 → 775,13
opB_rd <= dcdB_rd; |
op_pc <= dcd_pc; |
// |
`ifdef NG_EARLY_BRANCHING |
`ifdef OPT_EARLY_BRANCHING |
op_wr_pc <= ((dcdA_wr)&&(dcdA_pc)&&(dcdA[4] == dcd_gie))&&(~dcd_early_branch); |
`else |
op_wr_pc <= ((dcdA_wr)&&(dcdA_pc)&&(dcdA[4] == dcd_gie)); |
`endif |
|
`ifdef NG_PRECLEAR_BUS |
`ifdef OPT_PRECLEAR_BUS |
op_clear_bus <= dcd_clear_bus; |
`endif |
end |
777,9 → 819,24
opB_alu <= (opvalid_alu)&&(opR == dcdB)&&(dcdB_rd)&&(dcdI == 0); |
assign opB = (opB_alu) ? alu_result : r_opB; |
assign dcdB_stall = (dcdvalid)&&(dcdB_rd)&&( |
// Stall on memory ops writing to my register |
// (i.e. loads), or on any write to my |
// register if I have an immediate offset |
// 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. |
((opvalid)&&(opR_wr)&&(opR == dcdB) |
&&(opR != { op_gie, `CPU_PC_REG} ) |
&&((opvalid_mem)||(dcdI != 0))) |
// 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_wreg == dcdB))); |
assign dcdF_stall = (dcdvalid)&&((~dcdF[3])||(dcdA_cc)||(dcdB_cc)) |
&&(opvalid)&&(opR_cc); |
817,18 → 874,37
always @(posedge i_clk) |
if ((alu_ce)||(mem_ce)) |
alu_pc <= op_pc; |
`ifdef OPT_ILLEGAL_INSTRUCTION |
always @(posedge i_clk) |
if ((alu_ce)||(mem_ce)) |
alu_illegal <= op_illegal; |
`endif |
|
initial alu_pc_valid = 1'b0; |
always @(posedge i_clk) |
alu_pc_valid <= (~i_rst)&&(master_ce)&&(opvalid)&&(~clear_pipeline) |
alu_pc_valid <= (~i_rst)&&(master_ce)&&(~mem_rdbusy)&&(opvalid)&&(~clear_pipeline) |
&&((opvalid_alu)||(~mem_stalled)); |
|
`ifdef OPT_PIPELINED_BUS_ACCESS |
pipemem domem(i_clk, i_rst, mem_ce, |
(opn[0]), opB, opA, opR, |
mem_busy, mem_pipe_stalled, |
mem_valid, bus_err, mem_wreg, mem_result, |
mem_cyc_gbl, mem_cyc_lcl, |
mem_stb_gbl, mem_stb_lcl, |
mem_we, mem_addr, mem_data, |
mem_ack, mem_stall, mem_err, i_wb_data); |
|
`else // PIPELINED_BUS_ACCESS |
memops domem(i_clk, i_rst, mem_ce, |
(opn[0]), opB, opA, opR, |
mem_busy, mem_valid, bus_err, mem_wreg, mem_result, |
mem_busy, |
mem_valid, bus_err, mem_wreg, mem_result, |
mem_cyc_gbl, mem_cyc_lcl, |
mem_stb_gbl, mem_stb_lcl, |
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)); |
|
// Either the prefetch or the instruction gets the memory bus, but |
863,12 → 939,14
// bus instruction, so they don't need to be checked here. |
// Further, alu_wr includes (set_cond), so we don't need to |
// check for that here either. |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
assign wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid); |
`else |
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, |
// One or PC, one for CC, and one for GIE match |
assign wr_reg_id = (alu_wr)?alu_reg:mem_wreg; |
// Are we writing to the CC register? |
assign wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG); |
887,7 → 965,7
// 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); |
`ifdef NG_ILLEGAL_INSTRUCTION |
`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 }; |
`else |
939,7 → 1017,7
else if ((i_halt)&&(i_dbg_we) |
&&(i_dbg_reg == { 1'b0, `CPU_CC_REG })) |
break_en <= i_dbg_data[`CPU_BREAK_BIT]; |
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
assign o_break = ((break_en)||(~op_gie))&&(op_break) |
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy) |
&&(~clear_pipeline) |
949,7 → 1027,7
assign o_break = (((break_en)||(~op_gie))&&(op_break) |
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy) |
&&(~clear_pipeline)) |
||((~alu_gie)&&(bus_err)) |
||((~alu_gie)&&(bus_err)); |
`endif |
|
|
984,7 → 1062,7
else if ((i_halt)&&(i_dbg_we) |
&&(i_dbg_reg == { 1'b1, `CPU_CC_REG })) |
step <= i_dbg_data[`CPU_STEP_BIT]; |
else if ((master_ce)&&(alu_pc_valid)&&(step)&&(gie)) |
else if ((alu_pc_valid)&&(step)&&(gie)) |
step <= 1'b0; |
|
// The GIE register. Only interrupts can disable the interrupt register |
992,11 → 1070,11
// On interrupt (obviously) |
(i_interrupt) |
// If we are stepping the CPU |
||((master_ce)&&(alu_pc_valid)&&(step)) |
||((alu_pc_valid)&&(step)) |
// If we encounter a break instruction, if the break |
// enable isn't set. |
||((master_ce)&&(op_break)&&(~break_en)) |
`ifdef NG_ILLEGAL_INSTRUCTION |
||((master_ce)&&(~mem_rdbusy)&&(op_break)&&(~break_en)) |
`ifdef OPT_ILLEGAL_INSTRUCTION |
// On an illegal instruction |
||((alu_valid)&&(alu_illegal)) |
`endif |
1036,7 → 1114,7
else if (w_release_from_interrupt) |
trap <= 1'b0; |
|
`ifdef NG_ILLEGAL_INSTRUCTION |
`ifdef OPT_ILLEGAL_INSTRUCTION |
initial ill_err = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
1045,6 → 1123,8
ill_err <= 1'b0; |
else if ((alu_valid)&&(alu_illegal)&&(gie)) |
ill_err <= 1'b1; |
`else |
assign ill_err = 1'b0; |
`endif |
initial bus_err_flag = 1'b0; |
always @(posedge i_clk) |
1143,5 → 1223,5
// |
assign o_op_stall = (master_ce)&&((~opvalid)||(op_stall)); |
assign o_pf_stall = (master_ce)&&(~pf_valid); |
assign o_i_count = alu_pc_valid; |
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline); |
endmodule |