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 48 to Rev 47
    Reverse comparison

Rev 48 → Rev 47

/trunk/rtl/core/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
/trunk/rtl/core/pipefetch.v
54,18 → 54,18
i_wb_ack, i_wb_stall, i_wb_err, i_wb_data, i_wb_request,
o_illegal);
parameter RESET_ADDRESS=32'h0010_0000,
LGCACHELEN = 6, ADDRESS_WIDTH=24,
CACHELEN=(1<<LGCACHELEN), BUSW=32, AW=ADDRESS_WIDTH;
LGCACHELEN = 6, CACHELEN=(1<<LGCACHELEN),
BUSW=32;
input i_clk, i_rst, i_new_pc,
i_clear_cache, i_stall_n;
input [(AW-1):0] i_pc;
input [(BUSW-1):0] i_pc;
output reg [(BUSW-1):0] o_i;
output reg [(AW-1):0] o_pc;
output reg [(BUSW-1):0] o_pc;
output wire o_v;
//
output reg o_wb_cyc, o_wb_stb;
output wire o_wb_we;
output reg [(AW-1):0] o_wb_addr;
output reg [(BUSW-1):0] o_wb_addr;
output wire [(BUSW-1):0] o_wb_data;
//
input i_wb_ack, i_wb_stall, i_wb_err;
83,7 → 83,7
assign o_wb_we = 1'b0;
assign o_wb_data = 0;
 
reg [(AW-1):0] r_cache_base;
reg [(BUSW-1):0] r_cache_base;
reg [(LGCACHELEN):0] r_nvalid, r_acks_waiting;
reg [(BUSW-1):0] cache[0:(CACHELEN-1)];
 
90,10 → 90,10
reg [(LGCACHELEN-1):0] r_cache_offset;
 
reg r_addr_set;
reg [(AW-1):0] r_addr;
reg [(BUSW-1):0] r_addr;
 
wire [(AW-1):0] bus_nvalid;
assign bus_nvalid = { {(AW-LGCACHELEN-1){1'b0}}, r_nvalid };
wire [(BUSW-1):0] bus_nvalid;
assign bus_nvalid = { {(BUSW-LGCACHELEN-1){1'b0}}, r_nvalid };
 
// What are some of the conditions for which we need to restart the
// cache?
100,18 → 100,14
wire w_pc_out_of_bounds;
assign w_pc_out_of_bounds = ((i_new_pc)&&((r_nvalid == 0)
||(i_pc < r_cache_base)
||(i_pc >= r_cache_base + CACHELEN)
||(i_pc >= r_cache_base + bus_nvalid+5)));
||(i_pc >= r_cache_base + CACHELEN)));
wire w_ran_off_end_of_cache;
assign w_ran_off_end_of_cache =((r_addr_set)&&((r_addr < r_cache_base)
||(r_addr >= r_cache_base + CACHELEN)
||(r_addr >= r_cache_base + bus_nvalid+5)));
||(r_addr >= r_cache_base + CACHELEN)));
wire w_running_out_of_cache;
assign w_running_out_of_cache = (r_addr_set)
&&(r_addr >= r_cache_base + (1<<(LGCACHELEN-2))
+ (1<<(LGCACHELEN-1)))
&&(|r_nvalid[(LGCACHELEN):(LGCACHELEN-1)]);
 
+ (1<<(LGCACHELEN-1)));
initial r_cache_base = RESET_ADDRESS;
always @(posedge i_clk)
begin
/trunk/rtl/core/zipcpu.v
132,14 → 132,10
// `define OPT_SINGLE_FETCH
// (Best path--define these!)
`define OPT_CONDITIONAL_FLAGS
`define OPT_PRECLEAR_BUS
`define OPT_ILLEGAL_INSTRUCTION
`ifndef OPT_SINGLE_FETCH
// The following are pipeline optimization options.
// They make no sense in a single instruction fetch mode.
`define OPT_PRECLEAR_BUS
`define OPT_EARLY_BRANCHING
`define OPT_PIPELINED_BUS_ACCESS
`endif
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,
153,8 → 149,7
i_wb_err,
// Accounting/CPU usage interface
o_op_stall, o_pf_stall, o_i_count);
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
LGICACHE=6, AW=ADDRESS_WIDTH;
parameter RESET_ADDRESS=32'h0100000, LGICACHE=9;
input i_clk, i_rst, i_interrupt;
// Debug interface -- inputs
input i_halt, i_clear_pf_cache;
169,8 → 164,7
// Wishbone interface -- outputs
output wire o_wb_gbl_cyc, o_wb_gbl_stb;
output wire o_wb_lcl_cyc, o_wb_lcl_stb, o_wb_we;
output wire [(AW-1):0] o_wb_addr;
output wire [31:0] o_wb_data;
output wire [31:0] o_wb_addr, o_wb_data;
// Wishbone interface -- inputs
input i_wb_ack, i_wb_stall;
input [31:0] i_wb_data;
203,7 → 197,7
// PIPELINE STAGE #1 :: Prefetch
// Variable declarations
//
reg [(AW-1):0] pf_pc;
reg [31:0] pf_pc;
reg new_pc, op_break;
wire clear_pipeline;
assign clear_pipeline = new_pc || i_clear_pf_cache; // || op_break;
210,10 → 204,8
 
wire dcd_stalled;
wire pf_cyc, pf_stb, pf_we, pf_busy, pf_ack, pf_stall, pf_err;
wire [(AW-1):0] pf_addr;
wire [31:0] pf_data;
wire [31:0] instruction;
wire [(AW-1):0] instruction_pc;
wire [31:0] pf_addr, pf_data;
wire [31:0] instruction, instruction_pc;
wire pf_valid, instruction_gie, pf_illegal;
 
//
230,9 → 222,8
reg [3:0] dcdF;
reg dcdA_rd, dcdA_wr, dcdB_rd, dcdvalid,
dcdM, dcdF_wr, dcd_gie, dcd_break;
reg [(AW-1):0] dcd_pc;
reg [31:0] dcd_pc;
reg [23:0] r_dcdI;
reg dcd_zI; // true if dcdI == 0
wire dcdA_stall, dcdB_stall, dcdF_stall;
 
`ifdef OPT_PRECLEAR_BUS
242,11 → 233,11
reg dcd_illegal;
`endif
`ifdef OPT_EARLY_BRANCHING
reg dcd_early_branch_stb, dcd_early_branch;
reg [(AW-1):0] dcd_branch_pc;
reg dcd_early_branch_stb, dcd_early_branch;
reg [31:0] dcd_branch_pc;
`else
wire dcd_early_branch_stb, dcd_early_branch;
wire [(AW-1):0] dcd_branch_pc;
wire dcd_early_branch_stb, dcd_early_branch;
wire [31:0] dcd_branch_pc;
`endif
 
 
261,8 → 252,7
reg [4:0] alu_reg;
reg [3:0] opn;
reg [4:0] opR;
reg [31:0] r_opA, r_opB;
reg [(AW-1):0] op_pc;
reg [31:0] r_opA, r_opB, op_pc;
wire [31:0] w_opA, w_opB;
wire [31:0] opA_nowait, opB_nowait, opA, opB;
reg opR_wr, opR_cc, opF_wr, op_gie,
285,7 → 275,7
// Variable declarations
//
//
reg [(AW-1):0] alu_pc;
reg [31:0] alu_pc;
reg alu_pc_valid;;
wire alu_ce, alu_stall;
wire [31:0] alu_result;
307,12 → 297,10
`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;
wire [4:0] mem_wreg;
 
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 mem_busy, mem_rdbusy;
wire [31:0] mem_addr, mem_data, mem_result;
 
 
 
325,7 → 313,7
wire [4:0] wr_reg_id;
wire [31:0] wr_reg_vl;
wire w_switch_to_interrupt, w_release_from_interrupt;
reg [(AW-1):0] upc, ipc;
reg [31:0] upc, ipc;
 
 
 
408,14 → 396,13
wire pf_ce;
 
assign pf_ce = (~dcd_stalled);
prefetch #(ADDRESS_WIDTH)
pf(i_clk, i_rst, (pf_ce), pf_pc, gie,
prefetch pf(i_clk, i_rst, (pf_ce), pf_pc, gie,
instruction, instruction_pc, instruction_gie,
pf_valid, pf_illegal,
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, LGICACHE, ADDRESS_WIDTH)
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,
480,16 → 467,16
if (dcd_ce)
begin
if (instruction[31]) // Add
dcd_branch_pc <= instruction_pc+{ {(AW-20){instruction[19]}}, instruction[19:0] } + {{(AW-1){1'b0}},1'b1};
dcd_branch_pc <= instruction_pc+32'h01+{ {(12){instruction[19]}}, instruction[19:0] };
else if (~instruction[28]) // 4'h2 = MOV
dcd_branch_pc <= instruction_pc+{ {(AW-15){instruction[14]}}, instruction[14:0] } + {{(AW-1){1'b0}},1'b1};
dcd_branch_pc <= instruction_pc+32'h01+{ {(17){instruction[14]}}, instruction[14:0] };
else // if (instruction[28]) // 4'h3 = LDI
dcd_branch_pc <= instruction_pc+{ {(AW-24){instruction[23]}}, instruction[23:0] } + {{(AW-1){1'b0}},1'b1};
dcd_branch_pc <= instruction_pc+32'h01+{ {(8){instruction[23]}}, instruction[23:0] };
end
`else // OPT_EARLY_BRANCHING
assign dcd_early_branch_stb = 1'b0;
assign dcd_early_branch = 1'b0;
assign dcd_branch_pc = {(AW){1'b0}};
assign dcd_branch_pc = 32'h00;
`endif // OPT_EARLY_BRANCHING
 
always @(posedge i_clk)
535,7 → 522,6
dcdA_rd <= 1'b0;
dcdB_rd <= 1'b1;
r_dcdI <= { {(9){instruction[14]}}, instruction[14:0] };
dcd_zI <= (instruction[14:0] == 0);
dcdF_wr <= 1'b0; // Don't write flags
end
4'h3: begin // Load immediate
543,7 → 529,6
dcdA_rd <= 1'b0;
dcdB_rd <= 1'b0;
r_dcdI <= { instruction[23:0] };
dcd_zI <= (instruction[23:0] == 0);
dcdF_wr <= 1'b0; // Don't write flags
dcdF <= 4'h8; // This is unconditional
dcdOp <= 4'h2;
559,7 → 544,6
dcdF_wr <= (instruction[27:25] != 3'h7);
`endif
r_dcdI <= { 8'h00, instruction[15:0] };
dcd_zI <= (instruction[15:0] == 0);
if (instruction[27:24] == 4'he)
begin
// NOOP instruction
584,7 → 568,6
end else begin
// Actual multiply instruction
r_dcdI <= { 8'h00, instruction[15:0] };
dcd_zI <= (instruction[15:0] == 0);
dcdA_rd <= 1'b1;
dcdB_rd <= (instruction[19:16] != 4'hf);
dcdOp[3:0] <= (instruction[20])? 4'h4:4'h3;
595,13 → 578,9
dcdA_rd <= (instruction[28]); // Read on stores
dcdB_rd <= instruction[20];
if (instruction[20])
begin
r_dcdI <= { {(8){instruction[15]}}, instruction[15:0] };
dcd_zI <= (instruction[15:0] == 0);
end else begin
else
r_dcdI <= { {(4){instruction[19]}}, instruction[19:0] };
dcd_zI <= (instruction[19:0] == 0);
end
dcdM <= 1'b1; // Memory operation
`ifdef OPT_PRECLEAR_BUS
dcd_clear_bus <= (instruction[23:21]==3'h0);
612,13 → 591,10
dcdA_rd <= 1'b1;
dcdB_rd <= instruction[20];
if (instruction[20])
begin
r_dcdI <= { {(8){instruction[15]}}, instruction[15:0] };
dcd_zI <= (instruction[15:0] == 0);
end else begin
else
r_dcdI <= { {(4){instruction[19]}}, instruction[19:0] };
dcd_zI <= (instruction[19:0] == 0);
end end
end
endcase
 
 
669,33 → 645,25
if ((wr_reg_ce)&&(wr_reg_id == dcdA))
r_opA <= wr_reg_vl;
else if ((dcdA_pc)&&(dcdA[4] == dcd_gie))
r_opA <= { {(32-AW){1'b0}}, dcd_pc };
r_opA <= dcd_pc;
else if (dcdA_pc)
r_opA <= { {(32-AW){1'b0}}, upc };
r_opA <= upc;
else if (dcdA_cc)
r_opA <= { w_opA[31:11], (dcd_gie)?w_uflags:w_iflags };
else
r_opA <= w_opA;
end else if (opvalid)
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)||((opA_mem)&&(mem_valid)))
r_opA <= wr_reg_vl;
end
wire [31:0] dcdI, w_opBnI;
assign dcdI = { {(8){r_dcdI[23]}}, r_dcdI };
assign w_opBnI = (~dcdB_rd) ? 32'h00
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl
: (((dcdB_pc)&&(dcdB[4] == dcd_gie)) ? {{(32-AW){1'b0}},dcd_pc }
: ((dcdB_pc) ? {{(32-AW){1'b0}},upc}
: (((dcdB_pc)&&(dcdB[4] == dcd_gie)) ? dcd_pc
: ((dcdB_pc) ? upc
: ((dcdB_cc) ? { w_opB[31:11], (dcd_gie)?w_uflags:w_iflags}
: regset[dcdB]))));
always @(posedge i_clk)
if (op_ce) // &&(dcdvalid))
r_opB <= w_opBnI + dcdI;
else if ((opvalid)&&((opB_alu)||((opB_mem)&&(mem_valid))))
r_opB <= wr_reg_vl;
 
// The logic here has become more complex than it should be, no thanks
// to Xilinx's Vivado trying to help. The conditions are supposed to
805,6 → 773,7
// use that value.
opA_rd <= dcdA_rd;
opB_rd <= dcdB_rd;
op_pc <= dcd_pc;
//
`ifdef OPT_EARLY_BRANCHING
op_wr_pc <= ((dcdA_wr)&&(dcdA_pc)&&(dcdA[4] == dcd_gie))&&(~dcd_early_branch);
811,8 → 780,6
`else
op_wr_pc <= ((dcdA_wr)&&(dcdA_pc)&&(dcdA[4] == dcd_gie));
`endif
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
// op_pc <= dcd_pc;
 
`ifdef OPT_PRECLEAR_BUS
op_clear_bus <= dcd_clear_bus;
832,51 → 799,25
// We'll create a flag here to start our coordination. Once we
// define this flag to something other than just plain zero, then
// the stalls will already be in place.
reg opA_alu, opA_mem;
reg opA_alu;
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;
always @(posedge i_clk)
if (op_ce)
opA_mem <= ((opvalid_mem)&&(opR == dcdA)&&(dcdA_rd))
||((~opvalid)&&(mem_busy)&&(~mem_we)
&&(mem_last_reg == dcdA)&&(dcdA_rd));
else if ((opvalid)&&(opA_mem)&&(mem_valid))
opA_mem <= 1'b0;
opA_alu <= (opvalid_alu)&&(opR == dcdA)&&(dcdA_rd);
assign opA = (opA_alu) ? alu_result : r_opA;
 
always @(posedge i_clk)
if (mem_ce)
mem_last_reg <= opR;
assign opA = (opA_alu) ? alu_result
: ( ((opA_mem)&&(mem_valid))?mem_result
: r_opA );
 
assign dcdA_stall = (dcdvalid)&&(dcdA_rd)&&(
// Skip the requirement on writing back opA
// Stall on memory, since we'll always need to stall for a
// memory access anyway
// ((opvalid_mem)&&(opR_wr)&&(opR == dcdA))
((opvalid_alu)&&(opF_wr)&&(dcdA_cc)));
// Place stalls for this latter case into the ops stage
// ||((mem_busy)&&(~mem_we));
((opvalid_mem)&&(opR_wr)&&(opR == dcdA))||
((opvalid_alu)&&(opF_wr)&&(dcdA_cc))||
((mem_busy)&&(~mem_we)&&(mem_wreg == dcdA)));
 
reg opB_alu, opB_mem;
reg opB_alu;
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))
||((~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_result
: ( ((opB_mem)&&(mem_valid))?mem_result
: r_opB );
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
889,7 → 830,7
// here.
((opvalid)&&(opR_wr)&&(opR == dcdB)
&&(opR != { op_gie, `CPU_PC_REG} )
&&(~dcd_zI))
&&((opvalid_mem)||(dcdI != 0)))
// Stall on any write to the flags register,
// if we're going to need the flags value for
// opB.
896,7 → 837,7
||((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)));
||((mem_busy)&&(~mem_we)&&(mem_wreg == dcdB)));
assign dcdF_stall = (dcdvalid)&&((~dcdF[3])||(dcdA_cc)||(dcdB_cc))
&&(opvalid)&&(opR_cc);
//
945,7 → 886,7
&&((opvalid_alu)||(~mem_stalled));
 
`ifdef OPT_PIPELINED_BUS_ACCESS
pipemem #(AW) domem(i_clk, i_rst, mem_ce,
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,
955,7 → 896,7
mem_ack, mem_stall, mem_err, i_wb_data);
`else // PIPELINED_BUS_ACCESS
memops #(AW) domem(i_clk, i_rst, mem_ce,
memops domem(i_clk, i_rst, mem_ce,
(opn[0]), opB, opA, opR,
mem_busy,
mem_valid, bus_err, mem_wreg, mem_result,
968,7 → 909,7
 
// Either the prefetch or the instruction gets the memory bus, but
// never both.
wbdblpriarb #(32,AW) pformem(i_clk, i_rst,
wbdblpriarb #(32,32) pformem(i_clk, i_rst,
// Memory access to the arbiter, priority position
mem_cyc_gbl, mem_cyc_lcl, mem_stb_gbl, mem_stb_lcl,
mem_we, mem_addr, mem_data, mem_ack, mem_stall, mem_err,
1206,23 → 1147,23
// a non-gie instruction?
always @(posedge i_clk)
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
upc <= wr_reg_vl[(AW-1):0];
upc <= wr_reg_vl;
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];
upc <= i_dbg_data;
 
always @(posedge i_clk)
if (i_rst)
ipc <= RESET_ADDRESS;
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc))
ipc <= wr_reg_vl[(AW-1):0];
ipc <= wr_reg_vl;
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];
ipc <= i_dbg_data;
 
always @(posedge i_clk)
if (i_rst)
1232,10 → 1173,10
else if (w_release_from_interrupt)
pf_pc <= upc;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
pf_pc <= wr_reg_vl[(AW-1):0];
pf_pc <= wr_reg_vl;
else if ((i_halt)&&(i_dbg_we)
&&(i_dbg_reg[4:0] == { gie, `CPU_PC_REG}))
pf_pc <= i_dbg_data[(AW-1):0];
pf_pc <= i_dbg_data;
else if (dcd_ce)
pf_pc <= pf_pc + 1;
 
1261,7 → 1202,7
begin
o_dbg_reg <= regset[i_dbg_reg];
if (i_dbg_reg[3:0] == `CPU_PC_REG)
o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
o_dbg_reg[10:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
end
/trunk/rtl/core/memops.v
44,7 → 44,6
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);
parameter ADDRESS_WIDTH=24, AW=ADDRESS_WIDTH;
input i_clk, i_rst;
input i_stb;
// CPU interface
61,8 → 60,7
// 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 [(AW-1):0] o_wb_addr;
output reg [31:0] o_wb_data;
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;
103,7 → 101,7
begin
o_wb_we <= i_op;
o_wb_data <= i_data;
o_wb_addr <= i_addr[(AW-1):0];
o_wb_addr <= i_addr;
end
 
initial o_valid = 1'b0;
/trunk/rtl/core/prefetch.v
51,19 → 51,19
o_i, o_pc, o_aux, o_valid, o_illegal,
o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
i_wb_ack, i_wb_stall, i_wb_err, i_wb_data);
parameter ADDRESS_WIDTH=32, AUX_WIDTH = 1, AW=ADDRESS_WIDTH;
input i_clk, i_rst, i_ce;
input [(AW-1):0] i_pc;
input [(AUX_WIDTH-1):0] i_aux;
output reg [31:0] o_i;
output reg [(AW-1):0] o_pc;
output reg [(AUX_WIDTH-1):0] o_aux;
output wire o_valid, o_illegal;
parameter AW = 1;
input i_clk, i_rst, i_ce;
input [31:0] i_pc;
input [(AW-1):0] i_aux;
output reg [31:0] o_i;
output reg [31:0] o_pc;
output reg [(AW-1):0] o_aux;
output wire o_valid, o_illegal;
// Wishbone outputs
output reg o_wb_cyc, o_wb_stb;
output wire o_wb_we;
output reg [(AW-1):0] o_wb_addr;
output wire [31:0] o_wb_data;
output reg o_wb_cyc, o_wb_stb;
output wire o_wb_we;
output reg [31:0] o_wb_addr;
output wire [31:0] o_wb_data;
// And return inputs
input i_wb_ack, i_wb_stall, i_wb_err;
input [31:0] i_wb_data;
/trunk/rtl/zipsystem.v
162,14 → 162,12
// Wishbone slave interface for debugging purposes
i_dbg_cyc, i_dbg_stb, i_dbg_we, i_dbg_addr, i_dbg_data,
o_dbg_ack, o_dbg_stall, o_dbg_data);
parameter RESET_ADDRESS=24'h0100000, ADDRESS_WIDTH=24,
LGICACHE=6, START_HALTED=1, EXTERNAL_INTERRUPTS=1,
// Derived parameters
AW=ADDRESS_WIDTH;
parameter RESET_ADDRESS=32'h0100000, START_HALTED=1,
EXTERNAL_INTERRUPTS=1;
input i_clk, i_rst;
// Wishbone master
output wire o_wb_cyc, o_wb_stb, o_wb_we;
output wire [(AW-1):0] o_wb_addr;
output wire [31:0] o_wb_addr;
output wire [31:0] o_wb_data;
input i_wb_ack, i_wb_stall;
input [31:0] i_wb_data;
215,7 → 213,7
//
wire sys_cyc, sys_stb, sys_we;
wire [4:0] sys_addr;
wire [(AW-1):0] cpu_addr;
wire [31:0] cpu_addr;
wire [31:0] sys_data;
wire sys_ack, sys_stall;
 
445,11 → 443,10
wire [31:0] dmac_data;
wire dmac_ack, dmac_stall;
wire dc_cyc, dc_stb, dc_we, dc_ack, dc_stall;
wire [31:0] dc_data;
wire [(AW-1):0] dc_addr;
wire [31:0] dc_data, dc_addr;
wire cpu_gbl_cyc;
assign dmac_stb = (sys_stb)&&(sys_addr[4]);
wbdmac #(AW) dma_controller(i_clk,
wbdmac dma_controller(i_clk,
sys_cyc, dmac_stb, sys_we,
sys_addr[1:0], sys_data,
dmac_ack, dmac_stall, dmac_data,
561,8 → 558,7
wire [31:0] cpu_dbg_data;
assign cpu_dbg_we = ((dbg_cyc)&&(dbg_stb)&&(~cmd_addr[5])
&&(dbg_we)&&(dbg_addr));
zipcpu #(RESET_ADDRESS,ADDRESS_WIDTH,LGICACHE)
thecpu(i_clk, cpu_reset, pic_interrupt,
zipcpu #(RESET_ADDRESS) thecpu(i_clk, cpu_reset, pic_interrupt,
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we,
dbg_idata, cpu_dbg_stall, cpu_dbg_data,
cpu_dbg_cc, cpu_break,
616,9 → 612,8
wire ext_cyc, ext_stb, ext_we, ext_err;
wire cpu_ext_ack, cpu_ext_stall, ext_ack, ext_stall,
cpu_ext_err;
wire [(AW-1):0] ext_addr;
wire [31:0] ext_odata;
wbpriarbiter #(32,AW) dmacvcpu(i_clk, i_rst,
wire [31:0] ext_addr, ext_odata;
wbpriarbiter #(32,32) dmacvcpu(i_clk, i_rst,
cpu_gbl_cyc, cpu_gbl_stb, cpu_we, cpu_addr, cpu_data,
cpu_ext_ack, cpu_ext_stall, cpu_ext_err,
dc_cyc, dc_stb, dc_we, dc_addr, dc_data,
627,7 → 622,7
ext_ack, ext_stall, ext_err);
 
`ifdef DELAY_EXT_BUS
busdelay #(AW,32) extbus(i_clk,
busdelay #(32,32) extbus(i_clk,
ext_cyc, ext_stb, ext_we, ext_addr, ext_odata,
ext_ack, ext_stall, ext_idata, ext_err,
o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
/trunk/rtl/zipbones.v
42,19 → 42,18
// Wishbone slave interface for debugging purposes
i_dbg_cyc, i_dbg_stb, i_dbg_we, i_dbg_addr, i_dbg_data,
o_dbg_ack, o_dbg_stall, o_dbg_data);
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=32,
LGICACHE=6, START_HALTED=1,
AW=ADDRESS_WIDTH;
parameter RESET_ADDRESS=32'h0100000, START_HALTED=1,
EXTERNAL_INTERRUPTS=1;
input i_clk, i_rst;
// Wishbone master
output wire o_wb_cyc, o_wb_stb, o_wb_we;
output wire [(AW-1):0] o_wb_addr;
output wire [31:0] o_wb_addr;
output wire [31:0] o_wb_data;
input i_wb_ack, i_wb_stall;
input [31:0] i_wb_data;
input i_wb_err;
// Incoming interrupts
input i_ext_int;
input [(EXTERNAL_INTERRUPTS-1):0] i_ext_int;
// Outgoing interrupt
output wire o_ext_int;
// Wishbone slave
69,7 → 68,7
//
wire sys_cyc, sys_stb, sys_we;
wire [4:0] sys_addr;
wire [(AW-1):0] cpu_addr;
wire [31:0] cpu_addr;
wire [31:0] sys_data;
wire sys_ack, sys_stall;
 
139,7 → 138,7
// 0x01000 -> cc.sleep
// 0x02000 -> cc.gie
// 0x10000 -> External interrupt line is high
assign cmd_data = { 7'h00, 8'h00, i_ext_int,
assign cmd_data = { 7'h00, {(9-EXTERNAL_INTERRUPTS){1'b0}}, i_ext_int,
2'b00, cpu_dbg_cc,
1'b0, cmd_halt, (~cpu_dbg_stall), 1'b0,
pic_data[15], cpu_reset, 1'b0, cmd_addr };
157,8 → 156,7
wire [31:0] cpu_dbg_data;
assign cpu_dbg_we = ((i_dbg_cyc)&&(i_dbg_stb)
&&(i_dbg_we)&&(i_dbg_addr));
zipcpu #(RESET_ADDRESS,ADDRESS_WIDTH,LGICACHE)
thecpu(i_clk, cpu_reset, i_ext_int,
zipcpu #(RESET_ADDRESS) thecpu(i_clk, cpu_reset, i_ext_int,
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we,
i_dbg_data, cpu_dbg_stall, cpu_dbg_data,
cpu_dbg_cc, cpu_break,
/trunk/rtl/peripherals/wbdmac.v
113,8 → 113,7
i_dev_ints,
o_interrupt,
i_other_busmaster_requests_bus);
parameter ADDRESS_WIDTH=32, LGMEMLEN = 10,
DW=32, LGDV=5,AW=ADDRESS_WIDTH;
parameter LGMEMLEN = 10, DW=32, LGDV=5;
input i_clk;
// Slave/control wishbone inputs
input i_swb_cyc, i_swb_stb, i_swb_we;
126,8 → 125,7
output reg [(DW-1):0] o_swb_data;
// Master/DMA wishbone control
output reg o_mwb_cyc, o_mwb_stb, o_mwb_we;
output reg [(AW-1):0] o_mwb_addr;
output reg [(DW-1):0] o_mwb_data;
output reg [(DW-1):0] o_mwb_addr, o_mwb_data;
// Master/DMA wishbone responses from the bus
input i_mwb_ack, i_mwb_stall;
input [(DW-1):0] i_mwb_data;
142,7 → 140,7
 
reg cfg_wp; // Write protect
reg cfg_err;
reg [(AW-1):0] cfg_waddr, cfg_raddr, cfg_len;
reg [(DW-1):0] cfg_waddr, cfg_raddr, cfg_len;
reg [(LGMEMLEN-1):0] cfg_blocklen_sub_one;
reg cfg_incs, cfg_incd;
reg [(LGDV-1):0] cfg_dev_trigger;
153,14 → 151,14
 
reg [(DW-1):0] dma_mem [0:(((1<<LGMEMLEN))-1)];
reg [(LGMEMLEN):0] nread, nwritten, nacks;
wire [(AW-1):0] bus_nacks;
assign bus_nacks = { {(AW-LGMEMLEN-1){1'b0}}, nacks };
wire [(DW-1):0] bus_nacks;
assign bus_nacks = { {(DW-LGMEMLEN-1){1'b0}}, nacks };
 
initial o_interrupt = 1'b0;
initial o_mwb_cyc = 1'b0;
initial cfg_err = 1'b0;
initial cfg_wp = 1'b0;
initial cfg_len = {(AW){1'b0}};
initial cfg_len = 32'h00;
initial cfg_blocklen_sub_one = {(LGMEMLEN){1'b1}};
initial cfg_on_dev_trigger = 1'b0;
always @(posedge i_clk)
273,9 → 271,9
cfg_incd <= ~i_swb_data[28];
cfg_err <= 1'b0;
end
2'b01: cfg_len <= i_swb_data[(AW-1):0];
2'b10: cfg_raddr <= i_swb_data[(AW-1):0];
2'b11: cfg_waddr <= i_swb_data[(AW-1):0];
2'b01: cfg_len <= i_swb_data;
2'b10: cfg_raddr <= i_swb_data;
2'b11: cfg_waddr <= i_swb_data;
endcase
end
end
313,9 → 311,9
cfg_on_dev_trigger, cfg_dev_trigger,
cfg_blocklen_sub_one
};
2'b01: o_swb_data <= { {(DW-AW){1'b0}}, cfg_len };
2'b10: o_swb_data <= { {(DW-AW){1'b0}}, cfg_raddr};
2'b11: o_swb_data <= { {(DW-AW){1'b0}}, cfg_waddr};
2'b01: o_swb_data <= cfg_len;
2'b10: o_swb_data <= cfg_raddr;
2'b11: o_swb_data <= cfg_waddr;
endcase
 
always @(posedge i_clk)
/trunk/rtl/peripherals/zipport.v
0,0 → 1,129
///////////////////////////////////////////////////////////////////////////
//
// Filename: zipport.v
//
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
//
// Purpose: A communications port for passing data between CPU's in a
// multi-cpu system.
//
// Example: Imagine a signal processing system with many 'CPUs' working
// together. Each communicates its outputs to the next CPU.
// Writes to this port will send values to the next port over,
// and reads from this port will read such values.
//
// These ports are ripe for adding FIFO's too, but the port
// itself doesn't offer a FIFO. Worse, as written, the port
// offers no flags to a FIFO to know when to read the next
// value.
//
// Note: There are other means of message passing, this is just
// one--perhaps not even the best one.
//
// Interface:
// 2-bits of control:
// top bit means valid data that hasn't been read.
// next bit means data has not been read, but instead has been
// lost
// These statuses are cleared upon any read.
// 30-bits of data.
//
// External CPU:
// Can read/write to the port.
// Writes to the port take place by setting i_port_v and strobing i_port_w.
// Writes from this port to other ports take place the same way.
// Reads/writes to/from this port by the CPU take place via the single
// wishbone address.
//
//
// 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 zipport(i_clk,
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data,
i_port_w, i_port_v,
o_port_w, o_port_v,
o_int_full, o_int_ovflw);
parameter BW = 32, DW = (BW-2);
input i_clk;
// Wishbone inputs
input i_wb_cyc, i_wb_stb, i_wb_we;
input [(BW-1):0] i_wb_data;
// Wishbone outputs
output reg o_wb_ack;
output wire o_wb_stall;
output wire [(BW-1):0] o_wb_data;
// Port connections
input i_port_w; // Write strobe
input [(DW-1):0] i_port_v; // Value received
output reg o_port_w; // Writing strobe
output reg [(BW-1):0] o_port_v; // Value being sent
// Interrupt line
output wire o_int_full, o_int_ovflw;
 
wire wb_write, wb_read, wb_cycle;
assign wb_write = (i_wb_cyc)&&(i_wb_stb)&&(i_wb_we);
assign wb_read = (i_wb_cyc)&&(i_wb_stb)&&(~i_wb_we);
assign wb_cycle = (i_wb_cyc)&&(i_wb_stb);
 
reg r_valid, r_ovflw;
reg [(DW-1):0] r_data;
 
initial r_valid = 1'b0;
initial r_ovflw = 1'b0;
always @(posedge i_clk)
if (wb_write)
begin
o_port_w <= 1'b1;
o_port_v <= i_wb_data;
end else
o_port_w <= 1'b0;
 
always @(posedge i_clk)
if (i_port_w)
r_valid <= 1'b1;
else if (wb_read)
r_valid <= 1'b0;
 
always @(posedge i_clk)
if (i_port_w)
r_ovflw <= (r_valid);
else if (wb_read)
r_ovflw <= 1'b0;
 
always @(posedge i_clk)
if (i_port_w)
r_data <= i_port_v;
 
assign o_int_full = r_valid;
assign o_int_ovflw= r_ovflw;
 
initial o_wb_ack = 1'b0;
always @(posedge i_clk)
o_wb_ack <= wb_cycle;
assign o_wb_stall = 1'b0;
 
assign o_wb_data = { r_valid, r_ovflw, {(BW-2-DW){1'b0}}, r_data };
 
endmodule

powered by: WebSVN 2.1.0

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