Line 112... |
Line 112... |
`define CPU_STEP_BIT 6
|
`define CPU_STEP_BIT 6
|
`define CPU_GIE_BIT 5
|
`define CPU_GIE_BIT 5
|
`define CPU_SLEEP_BIT 4
|
`define CPU_SLEEP_BIT 4
|
module zipcpu(i_clk, i_rst, i_interrupt,
|
module zipcpu(i_clk, i_rst, i_interrupt,
|
// Debug interface
|
// Debug interface
|
i_halt, i_dbg_reg, i_dbg_we, i_dbg_data,
|
i_halt, i_clear_pf_cache, i_dbg_reg, i_dbg_we, i_dbg_data,
|
o_dbg_stall, o_dbg_reg,
|
o_dbg_stall, o_dbg_reg, o_dbg_cc,
|
o_break,
|
o_break,
|
// CPU interface to the wishbone bus
|
// CPU interface to the wishbone bus
|
o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
|
o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
|
i_wb_ack, i_wb_stall, i_wb_data,
|
i_wb_ack, i_wb_stall, i_wb_data,
|
// Accounting/CPU usage interface
|
// Accounting/CPU usage interface
|
o_op_stall, o_pf_stall, o_i_count);
|
o_op_stall, o_pf_stall, o_i_count);
|
parameter RESET_ADDRESS=32'h0100000;
|
parameter RESET_ADDRESS=32'h0100000;
|
input i_clk, i_rst, i_interrupt;
|
input i_clk, i_rst, i_interrupt;
|
// Debug interface -- inputs
|
// Debug interface -- inputs
|
input i_halt;
|
input i_halt, i_clear_pf_cache;
|
input [4:0] i_dbg_reg;
|
input [4:0] i_dbg_reg;
|
input i_dbg_we;
|
input i_dbg_we;
|
input [31:0] i_dbg_data;
|
input [31:0] i_dbg_data;
|
// Debug interface -- outputs
|
// Debug interface -- outputs
|
output reg o_dbg_stall;
|
output reg o_dbg_stall;
|
output reg [31:0] o_dbg_reg;
|
output reg [31:0] o_dbg_reg;
|
|
output reg [3:0] o_dbg_cc;
|
output wire o_break;
|
output wire o_break;
|
// Wishbone interface -- outputs
|
// Wishbone interface -- outputs
|
output wire o_wb_cyc, o_wb_stb, o_wb_we;
|
output wire o_wb_cyc, o_wb_stb, o_wb_we;
|
output wire [31:0] o_wb_addr, o_wb_data;
|
output wire [31:0] o_wb_addr, o_wb_data;
|
// Wishbone interface -- inputs
|
// Wishbone interface -- inputs
|
Line 161... |
Line 162... |
// PIPELINE STAGE #1 :: Prefetch
|
// PIPELINE STAGE #1 :: Prefetch
|
// Variable declarations
|
// Variable declarations
|
//
|
//
|
reg [31:0] pf_pc;
|
reg [31:0] pf_pc;
|
reg new_pc;
|
reg new_pc;
|
|
wire clear_pipeline;
|
|
assign clear_pipeline = new_pc || i_clear_pf_cache;
|
|
|
wire dcd_stalled;
|
wire dcd_stalled;
|
wire pf_cyc, pf_stb, pf_we, pf_busy, pf_ack, pf_stall;
|
wire pf_cyc, pf_stb, pf_we, pf_busy, pf_ack, pf_stall;
|
wire [31:0] pf_addr, pf_data;
|
wire [31:0] pf_addr, pf_data;
|
wire [31:0] instruction, instruction_pc;
|
wire [31:0] instruction, instruction_pc;
|
Line 281... |
Line 284... |
//
|
//
|
// PIPELINE STAGE #4 :: ALU / Memory
|
// PIPELINE STAGE #4 :: ALU / Memory
|
// Calculate stall conditions
|
// Calculate stall conditions
|
assign alu_stall = (((~master_ce)||(mem_rdbusy))&&(opvalid)&&(~opM))
|
assign alu_stall = (((~master_ce)||(mem_rdbusy))&&(opvalid)&&(~opM))
|
||((opvalid)&&(wr_reg_ce)&&(wr_reg_id == { op_gie, `CPU_PC_REG }));
|
||((opvalid)&&(wr_reg_ce)&&(wr_reg_id == { op_gie, `CPU_PC_REG }));
|
assign alu_ce = (master_ce)&&(opvalid)&&(~opM)&&(~alu_stall)&&(~new_pc);
|
assign alu_ce = (master_ce)&&(opvalid)&&(~opM)&&(~alu_stall)&&(~clear_pipeline);
|
//
|
//
|
assign mem_ce = (master_ce)&&(opvalid)&&(opM)&&(~mem_stalled)&&(~new_pc)&&(set_cond);
|
assign mem_ce = (master_ce)&&(opvalid)&&(opM)&&(~mem_stalled)&&(~clear_pipeline)&&(set_cond);
|
assign mem_stalled = (mem_busy)||((opvalid)&&(opM)&&(
|
assign mem_stalled = (mem_busy)||((opvalid)&&(opM)&&(
|
(~master_ce)
|
(~master_ce)
|
// Stall waiting for flags to be valid
|
// Stall waiting for flags to be valid
|
||((~opF[8])&&(
|
||((~opF[8])&&(
|
((wr_reg_ce)&&(wr_reg_id[4:0] == {op_gie,`CPU_CC_REG}))))
|
((wr_reg_ce)&&(wr_reg_id[4:0] == {op_gie,`CPU_CC_REG}))))
|
Line 312... |
Line 315... |
pf_cyc, pf_stb, pf_we, pf_addr,
|
pf_cyc, pf_stb, pf_we, pf_addr,
|
pf_data,
|
pf_data,
|
pf_ack, pf_stall, i_wb_data);
|
pf_ack, pf_stall, i_wb_data);
|
`else // Pipe fetch
|
`else // Pipe fetch
|
pipefetch #(RESET_ADDRESS)
|
pipefetch #(RESET_ADDRESS)
|
pf(i_clk, i_rst, new_pc, ~dcd_stalled, pf_pc,
|
pf(i_clk, i_rst, new_pc, i_clear_pf_cache, ~dcd_stalled, pf_pc,
|
instruction, instruction_pc, pf_valid,
|
instruction, instruction_pc, pf_valid,
|
pf_cyc, pf_stb, pf_we, pf_addr, pf_data,
|
pf_cyc, pf_stb, pf_we, pf_addr, pf_data,
|
pf_ack, pf_stall, i_wb_data,
|
pf_ack, pf_stall, i_wb_data,
|
mem_cyc);
|
mem_cyc);
|
assign instruction_gie = gie;
|
assign instruction_gie = gie;
|
Line 324... |
Line 327... |
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst)
|
if (i_rst)
|
dcdvalid <= 1'b0;
|
dcdvalid <= 1'b0;
|
else if (dcd_ce)
|
else if (dcd_ce)
|
dcdvalid <= (~new_pc);
|
dcdvalid <= (~clear_pipeline);
|
else if ((~dcd_stalled)||(new_pc))
|
else if ((~dcd_stalled)||(clear_pipeline))
|
dcdvalid <= 1'b0;
|
dcdvalid <= 1'b0;
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (dcd_ce)
|
if (dcd_ce)
|
begin
|
begin
|
Line 509... |
Line 512... |
// have in our queue. This instruction must then
|
// have in our queue. This instruction must then
|
// move forward, and get a stall cycle inserted.
|
// move forward, and get a stall cycle inserted.
|
// Hence, the test on dcd_stalled here. If we must
|
// Hence, the test on dcd_stalled here. If we must
|
// wait until our operands are valid, then we aren't
|
// wait until our operands are valid, then we aren't
|
// valid yet until then.
|
// valid yet until then.
|
opvalid<= (~new_pc)&&(dcdvalid)&&(~dcd_stalled);
|
opvalid<= (~clear_pipeline)&&(dcdvalid)&&(~dcd_stalled);
|
else if ((~op_stall)||(new_pc))
|
else if ((~op_stall)||(clear_pipeline))
|
opvalid <= 1'b0;
|
opvalid <= 1'b0;
|
|
|
// Here's part of our debug interface. When we recognize a break
|
// Here's part of our debug interface. When we recognize a break
|
// instruction, we set the op_break flag. That'll prevent this
|
// instruction, we set the op_break flag. That'll prevent this
|
// instruction from entering the ALU, and cause an interrupt before
|
// instruction from entering the ALU, and cause an interrupt before
|
Line 526... |
Line 529... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst)
|
if (i_rst)
|
op_break <= 1'b0;
|
op_break <= 1'b0;
|
else if (op_ce)
|
else if (op_ce)
|
op_break <= (dcd_break)&&(r_dcdI[15:0] == 16'h0001);
|
op_break <= (dcd_break)&&(r_dcdI[15:0] == 16'h0001);
|
else if ((~op_stall)||(new_pc))
|
else if ((~op_stall)||(clear_pipeline))
|
op_break <= 1'b0;
|
op_break <= 1'b0;
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (op_ce)
|
if (op_ce)
|
begin
|
begin
|
Line 624... |
Line 627... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((alu_ce)||(mem_ce))
|
if ((alu_ce)||(mem_ce))
|
alu_pc <= op_pc;
|
alu_pc <= op_pc;
|
initial alu_pc_valid = 1'b0;
|
initial alu_pc_valid = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
alu_pc_valid <= (~i_rst)&&(master_ce)&&(opvalid)&&(~new_pc)
|
alu_pc_valid <= (~i_rst)&&(master_ce)&&(opvalid)&&(~clear_pipeline)
|
&&((~opM)
|
&&((~opM)
|
||(~mem_stalled));
|
||(~mem_stalled));
|
|
|
memops domem(i_clk, i_rst, mem_ce,
|
memops domem(i_clk, i_rst, mem_ce,
|
(opn[0]), opB, opA, opR,
|
(opn[0]), opB, opA, opR,
|
Line 674... |
Line 677... |
// What value to write?
|
// What value to write?
|
assign wr_reg_vl = (alu_wr)?alu_result:mem_result;
|
assign wr_reg_vl = (alu_wr)?alu_result:mem_result;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (wr_reg_ce)
|
if (wr_reg_ce)
|
regset[wr_reg_id] <= wr_reg_vl;
|
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 ...
|
// Write back to the condition codes/flags register ...
|
// When shall we write to our flags register? alF_wr already
|
// When shall we write to our flags register? alF_wr already
|
// includes the set condition ...
|
// includes the set condition ...
|
Line 830... |
Line 835... |
else if (dcd_ce)
|
else if (dcd_ce)
|
pf_pc <= pf_pc + 1;
|
pf_pc <= pf_pc + 1;
|
|
|
initial new_pc = 1'b1;
|
initial new_pc = 1'b1;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_rst)
|
if ((i_rst)||(i_clear_pf_cache))
|
new_pc <= 1'b1;
|
new_pc <= 1'b1;
|
else if (w_switch_to_interrupt)
|
else if (w_switch_to_interrupt)
|
new_pc <= 1'b1;
|
new_pc <= 1'b1;
|
else if (w_release_from_interrupt)
|
else if (w_release_from_interrupt)
|
new_pc <= 1'b1;
|
new_pc <= 1'b1;
|
Line 856... |
Line 861... |
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
|
o_dbg_reg <= { 25'h00, step, gie, sleep,
|
o_dbg_reg <= { 25'h00, step, gie, sleep,
|
((i_dbg_reg[4])?flags:iflags) };
|
((i_dbg_reg[4])?flags:iflags) };
|
end
|
end
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
|
o_dbg_cc <= { break_en, step, gie, sleep };
|
|
|
|
always @(posedge i_clk)
|
o_dbg_stall <= (~i_halt)||(pf_cyc)||(mem_cyc)||(mem_busy)
|
o_dbg_stall <= (~i_halt)||(pf_cyc)||(mem_cyc)||(mem_busy)
|
||((~opvalid)&&(~i_rst))
|
||((~opvalid)&&(~i_rst))
|
||((~dcdvalid)&&(~i_rst));
|
||((~dcdvalid)&&(~i_rst));
|
|
|
//
|
//
|