Line 1... |
Line 1... |
///////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Filename: zipsystem.v
|
// Filename: zipsystem.v
|
//
|
//
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
//
|
//
|
Line 60... |
Line 60... |
// watchdog-timers,
|
// watchdog-timers,
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Technology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
|
//
|
//
|
// This program is free software (firmware): you can redistribute it and/or
|
// 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
|
// 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
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// your option) any later version.
|
// your option) any later version.
|
Line 74... |
Line 74... |
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
|
|
// target there if the PDF file isn't present.) If not, see
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
|
//
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// http://www.gnu.org/licenses/gpl.html
|
// http://www.gnu.org/licenses/gpl.html
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
//
|
//
|
`include "cpudefs.v"
|
`include "cpudefs.v"
|
//
|
//
|
// While I hate adding delays to any bus access, this next delay is required
|
// While I hate adding delays to any bus access, this next delay is required
|
// to make timing close in my Basys-3 design.
|
// to make timing close in my Basys-3 design.
|
Line 155... |
Line 161... |
//
|
//
|
//
|
//
|
//
|
//
|
module zipsystem(i_clk, i_rst,
|
module zipsystem(i_clk, i_rst,
|
// Wishbone master interface from the CPU
|
// Wishbone master interface from the CPU
|
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, o_wb_sel,
|
i_wb_ack, i_wb_stall, i_wb_data, i_wb_err,
|
i_wb_ack, i_wb_stall, i_wb_data, i_wb_err,
|
// Incoming interrupts
|
// Incoming interrupts
|
i_ext_int,
|
i_ext_int,
|
// Our one outgoing interrupt
|
// Our one outgoing interrupt
|
o_ext_int,
|
o_ext_int,
|
Line 168... |
Line 174... |
o_dbg_ack, o_dbg_stall, o_dbg_data
|
o_dbg_ack, o_dbg_stall, o_dbg_data
|
`ifdef DEBUG_SCOPE
|
`ifdef DEBUG_SCOPE
|
, o_cpu_debug
|
, o_cpu_debug
|
`endif
|
`endif
|
);
|
);
|
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=32,
|
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=30,
|
LGICACHE=10, START_HALTED=1, EXTERNAL_INTERRUPTS=1,
|
LGICACHE=10, START_HALTED=1, EXTERNAL_INTERRUPTS=1,
|
`ifdef OPT_MULTIPLY
|
`ifdef OPT_MULTIPLY
|
IMPLEMENT_MPY = `OPT_MULTIPLY,
|
IMPLEMENT_MPY = `OPT_MULTIPLY,
|
`else
|
`else
|
IMPLEMENT_MPY = 0,
|
IMPLEMENT_MPY = 0,
|
Line 185... |
Line 191... |
`ifdef OPT_IMPLEMENT_FPU
|
`ifdef OPT_IMPLEMENT_FPU
|
IMPLEMENT_FPU=1,
|
IMPLEMENT_FPU=1,
|
`else
|
`else
|
IMPLEMENT_FPU=0,
|
IMPLEMENT_FPU=0,
|
`endif
|
`endif
|
IMPLEMENT_LOCK=1,
|
IMPLEMENT_LOCK=1;
|
HIGHSPEED_CPU=0,
|
localparam // Derived parameters
|
// Derived parameters
|
|
AW=ADDRESS_WIDTH;
|
AW=ADDRESS_WIDTH;
|
input i_clk, i_rst;
|
input i_clk, i_rst;
|
// Wishbone master
|
// Wishbone master
|
output wire o_wb_cyc, o_wb_stb, o_wb_we;
|
output wire o_wb_cyc, o_wb_stb, o_wb_we;
|
output wire [(AW-1):0] o_wb_addr;
|
output wire [(AW-1):0] o_wb_addr;
|
output wire [31:0] o_wb_data;
|
output wire [31:0] o_wb_data;
|
|
output wire [3:0] o_wb_sel;
|
input i_wb_ack, i_wb_stall;
|
input i_wb_ack, i_wb_stall;
|
input [31:0] i_wb_data;
|
input [31:0] i_wb_data;
|
input i_wb_err;
|
input i_wb_err;
|
// Incoming interrupts
|
// Incoming interrupts
|
input [(EXTERNAL_INTERRUPTS-1):0] i_ext_int;
|
input [(EXTERNAL_INTERRUPTS-1):0] i_ext_int;
|
Line 219... |
Line 225... |
// Handle our interrupt vector generation/coordination
|
// Handle our interrupt vector generation/coordination
|
wire [14:0] main_int_vector, alt_int_vector;
|
wire [14:0] main_int_vector, alt_int_vector;
|
wire ctri_int, tma_int, tmb_int, tmc_int, jif_int, dmac_int;
|
wire ctri_int, tma_int, tmb_int, tmc_int, jif_int, dmac_int;
|
wire mtc_int, moc_int, mpc_int, mic_int,
|
wire mtc_int, moc_int, mpc_int, mic_int,
|
utc_int, uoc_int, upc_int, uic_int;
|
utc_int, uoc_int, upc_int, uic_int;
|
|
|
|
assign main_int_vector[5:0] = { ctri_int, tma_int, tmb_int, tmc_int,
|
|
jif_int, dmac_int };
|
|
|
generate
|
generate
|
if (EXTERNAL_INTERRUPTS < 9)
|
if (EXTERNAL_INTERRUPTS < 9)
|
assign main_int_vector = { {(9-EXTERNAL_INTERRUPTS){1'b0}},
|
assign main_int_vector[14:6] = { {(9-EXTERNAL_INTERRUPTS){1'b0}},
|
i_ext_int, ctri_int,
|
i_ext_int };
|
tma_int, tmb_int, tmc_int,
|
|
jif_int, dmac_int };
|
|
else
|
else
|
assign main_int_vector = { i_ext_int[8:0], ctri_int,
|
assign main_int_vector[14:6] = i_ext_int[8:0];
|
tma_int, tmb_int, tmc_int,
|
|
jif_int, dmac_int };
|
|
endgenerate
|
endgenerate
|
generate
|
generate
|
if (EXTERNAL_INTERRUPTS <= 9)
|
if (EXTERNAL_INTERRUPTS <= 9)
|
`ifdef INCLUDE_ACCOUNTING_COUNTERS
|
`ifdef INCLUDE_ACCOUNTING_COUNTERS
|
assign alt_int_vector = { 7'h00,
|
assign alt_int_vector = { 7'h00,
|
Line 258... |
Line 264... |
wire dbg_cyc, dbg_stb, dbg_we, dbg_addr, dbg_stall;
|
wire dbg_cyc, dbg_stb, dbg_we, dbg_addr, dbg_stall;
|
wire [31:0] dbg_idata, dbg_odata;
|
wire [31:0] dbg_idata, dbg_odata;
|
reg dbg_ack;
|
reg dbg_ack;
|
`ifdef DELAY_DBG_BUS
|
`ifdef DELAY_DBG_BUS
|
wire dbg_err, no_dbg_err;
|
wire dbg_err, no_dbg_err;
|
|
wire [3:0] dbg_sel;
|
assign dbg_err = 1'b0;
|
assign dbg_err = 1'b0;
|
busdelay #(1,32) wbdelay(i_clk,
|
busdelay #(1,32) wbdelay(i_clk,
|
i_dbg_cyc, i_dbg_stb, i_dbg_we, i_dbg_addr, i_dbg_data,
|
i_dbg_cyc, i_dbg_stb, i_dbg_we, i_dbg_addr, i_dbg_data, 4'hf,
|
o_dbg_ack, o_dbg_stall, o_dbg_data, no_dbg_err,
|
o_dbg_ack, o_dbg_stall, o_dbg_data, no_dbg_err,
|
dbg_cyc, dbg_stb, dbg_we, dbg_addr, dbg_idata,
|
dbg_cyc, dbg_stb, dbg_we, dbg_addr, dbg_idata, dbg_sel,
|
dbg_ack, dbg_stall, dbg_odata, dbg_err);
|
dbg_ack, dbg_stall, dbg_odata, dbg_err);
|
`else
|
`else
|
assign dbg_cyc = i_dbg_cyc;
|
assign dbg_cyc = i_dbg_cyc;
|
assign dbg_stb = i_dbg_stb;
|
assign dbg_stb = i_dbg_stb;
|
assign dbg_we = i_dbg_we;
|
assign dbg_we = i_dbg_we;
|
Line 670... |
Line 677... |
// The CPU itself
|
// The CPU itself
|
//
|
//
|
wire cpu_gbl_stb, cpu_lcl_cyc, cpu_lcl_stb,
|
wire cpu_gbl_stb, cpu_lcl_cyc, cpu_lcl_stb,
|
cpu_we, cpu_dbg_we;
|
cpu_we, cpu_dbg_we;
|
wire [31:0] cpu_data, wb_data;
|
wire [31:0] cpu_data, wb_data;
|
|
wire [3:0] cpu_sel;
|
wire cpu_ack, cpu_stall, cpu_err;
|
wire cpu_ack, cpu_stall, cpu_err;
|
wire [31:0] cpu_dbg_data;
|
wire [31:0] cpu_dbg_data;
|
assign cpu_dbg_we = ((dbg_cyc)&&(dbg_stb)&&(~cmd_addr[5])
|
assign cpu_dbg_we = ((dbg_cyc)&&(dbg_stb)&&(~cmd_addr[5])
|
&&(dbg_we)&&(dbg_addr));
|
&&(dbg_we)&&(dbg_addr));
|
|
|
generate
|
|
if (HIGHSPEED_CPU==0)
|
|
begin
|
|
zipcpu #(
|
zipcpu #(
|
.RESET_ADDRESS(RESET_ADDRESS),
|
.RESET_ADDRESS(RESET_ADDRESS),
|
.ADDRESS_WIDTH(ADDRESS_WIDTH),
|
.ADDRESS_WIDTH(ADDRESS_WIDTH),
|
.LGICACHE(LGICACHE),
|
.LGICACHE(LGICACHE),
|
.IMPLEMENT_MPY(IMPLEMENT_MPY),
|
.IMPLEMENT_MPY(IMPLEMENT_MPY),
|
Line 693... |
Line 697... |
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we,
|
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we,
|
dbg_idata, cpu_dbg_stall, cpu_dbg_data,
|
dbg_idata, cpu_dbg_stall, cpu_dbg_data,
|
cpu_dbg_cc, cpu_break,
|
cpu_dbg_cc, cpu_break,
|
cpu_gbl_cyc, cpu_gbl_stb,
|
cpu_gbl_cyc, cpu_gbl_stb,
|
cpu_lcl_cyc, cpu_lcl_stb,
|
cpu_lcl_cyc, cpu_lcl_stb,
|
cpu_we, cpu_addr, cpu_data,
|
cpu_we, cpu_addr, cpu_data, cpu_sel,
|
cpu_ack, cpu_stall, wb_data,
|
cpu_ack, cpu_stall, wb_data,
|
cpu_err,
|
cpu_err,
|
cpu_op_stall, cpu_pf_stall, cpu_i_count
|
cpu_op_stall, cpu_pf_stall, cpu_i_count
|
`ifdef DEBUG_SCOPE
|
`ifdef DEBUG_SCOPE
|
, o_cpu_debug
|
, o_cpu_debug
|
`endif
|
`endif
|
);
|
);
|
end else begin
|
|
zipcpu #(
|
|
.RESET_ADDRESS(RESET_ADDRESS),
|
|
.ADDRESS_WIDTH(ADDRESS_WIDTH),
|
|
.LGICACHE(LGICACHE),
|
|
.IMPLEMENT_MPY(IMPLEMENT_MPY),
|
|
.IMPLEMENT_DIVIDE(IMPLEMENT_DIVIDE),
|
|
.IMPLEMENT_FPU(IMPLEMENT_FPU),
|
|
.IMPLEMENT_LOCK(IMPLEMENT_LOCK)
|
|
)
|
|
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,
|
|
cpu_gbl_cyc, cpu_gbl_stb,
|
|
cpu_lcl_cyc, cpu_lcl_stb,
|
|
cpu_we, cpu_addr, cpu_data,
|
|
cpu_ack, cpu_stall, wb_data,
|
|
cpu_err,
|
|
cpu_op_stall, cpu_pf_stall, cpu_i_count
|
|
`ifdef DEBUG_SCOPE
|
|
, o_cpu_debug
|
|
`endif
|
|
);
|
|
end endgenerate
|
|
|
|
// Now, arbitrate the bus ... first for the local peripherals
|
// Now, arbitrate the bus ... first for the local peripherals
|
// For the debugger to have access to the local system bus, the
|
// For the debugger to have access to the local system bus, the
|
// following must be true:
|
// following must be true:
|
// (dbg_cyc) The debugger must request the bus
|
// (dbg_cyc) The debugger must request the bus
|
Line 772... |
Line 751... |
wire ext_cyc, ext_stb, ext_we, ext_err;
|
wire ext_cyc, ext_stb, ext_we, ext_err;
|
wire cpu_ext_ack, cpu_ext_stall, ext_ack, ext_stall,
|
wire cpu_ext_ack, cpu_ext_stall, ext_ack, ext_stall,
|
cpu_ext_err;
|
cpu_ext_err;
|
wire [(AW-1):0] ext_addr;
|
wire [(AW-1):0] ext_addr;
|
wire [31:0] ext_odata;
|
wire [31:0] ext_odata;
|
|
wire [3:0] ext_sel;
|
wbpriarbiter #(32,AW) dmacvcpu(i_clk,
|
wbpriarbiter #(32,AW) dmacvcpu(i_clk,
|
cpu_gbl_cyc, cpu_gbl_stb, cpu_we, cpu_addr, cpu_data,
|
cpu_gbl_cyc, cpu_gbl_stb, cpu_we, cpu_addr, cpu_data, cpu_sel,
|
cpu_ext_ack, cpu_ext_stall, cpu_ext_err,
|
cpu_ext_ack, cpu_ext_stall, cpu_ext_err,
|
dc_cyc, dc_stb, dc_we, dc_addr, dc_data,
|
dc_cyc, dc_stb, dc_we, dc_addr, dc_data, 4'hf,
|
dc_ack, dc_stall, dc_err,
|
dc_ack, dc_stall, dc_err,
|
ext_cyc, ext_stb, ext_we, ext_addr, ext_odata,
|
ext_cyc, ext_stb, ext_we, ext_addr, ext_odata, ext_sel,
|
ext_ack, ext_stall, ext_err);
|
ext_ack, ext_stall, ext_err);
|
|
|
`ifdef DELAY_EXT_BUS
|
`ifdef DELAY_EXT_BUS
|
busdelay #(AW,32) extbus(i_clk,
|
busdelay #(AW,32) extbus(i_clk,
|
ext_cyc, ext_stb, ext_we, ext_addr, ext_odata,
|
ext_cyc, ext_stb, ext_we, ext_addr, ext_odata,
|
ext_ack, ext_stall, ext_idata, ext_err,
|
ext_ack, ext_stall, ext_idata, ext_err,
|
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, o_wb_sel,
|
i_wb_ack, i_wb_stall, i_wb_data, (i_wb_err)||(wdbus_int));
|
i_wb_ack, i_wb_stall, i_wb_data, (i_wb_err)||(wdbus_int));
|
`else
|
`else
|
assign o_wb_cyc = ext_cyc;
|
assign o_wb_cyc = ext_cyc;
|
assign o_wb_stb = ext_stb;
|
assign o_wb_stb = ext_stb;
|
assign o_wb_we = ext_we;
|
assign o_wb_we = ext_we;
|
assign o_wb_addr = ext_addr;
|
assign o_wb_addr = ext_addr;
|
assign o_wb_data = ext_odata;
|
assign o_wb_data = ext_odata;
|
|
assign o_wb_sel = ext_sel;
|
assign ext_ack = i_wb_ack;
|
assign ext_ack = i_wb_ack;
|
assign ext_stall = i_wb_stall;
|
assign ext_stall = i_wb_stall;
|
assign ext_idata = i_wb_data;
|
assign ext_idata = i_wb_data;
|
assign ext_err = (i_wb_err)||(wdbus_int);
|
assign ext_err = (i_wb_err)||(wdbus_int);
|
`endif
|
`endif
|