URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
[/] [zipcpu/] [trunk/] [rtl/] [zipbones.v] - Rev 209
Compare with Previous | Blame | View Log
//////////////////////////////////////////////////////////////////////////////// // // Filename: zipbones.v // // Project: Zip CPU -- a small, lightweight, RISC CPU soft core // // Purpose: In the spirit of keeping the Zip CPU small, this implements a // Zip System with no peripherals: Any peripherals you wish will // need to be implemented off-module. // // Creator: Dan Gisselquist, Ph.D. // Gisselquist Technology, LLC // //////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015-2019, 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. // // 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, // http://www.gnu.org/licenses/gpl.html // // //////////////////////////////////////////////////////////////////////////////// // // `default_nettype none // `include "cpudefs.v" // `define RESET_BIT 6 `define STEP_BIT 8 `define HALT_BIT 10 `define CLEAR_CACHE_BIT 11 // module zipbones(i_clk, i_reset, // Wishbone master interface from the CPU 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, // Incoming interrupts i_ext_int, // Our one outgoing interrupt o_ext_int, // 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 `ifdef DEBUG_SCOPE , o_cpu_debug `endif ); parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=30, LGICACHE=8; parameter [0:0] START_HALTED=0; parameter EXTERNAL_INTERRUPTS=1, `ifdef OPT_MULTIPLY IMPLEMENT_MPY = `OPT_MULTIPLY; `else IMPLEMENT_MPY = 0; `endif parameter [0:0] `ifdef OPT_DIVIDE IMPLEMENT_DIVIDE=1, `else IMPLEMENT_DIVIDE=0, `endif `ifdef OPT_IMPLEMENT_FPU IMPLEMENT_FPU=1, `else IMPLEMENT_FPU=0, `endif IMPLEMENT_LOCK=1; localparam // Derived parameters PHYSICAL_ADDRESS_WIDTH=ADDRESS_WIDTH, PAW=ADDRESS_WIDTH, `ifdef OPT_MMU VIRTUAL_ADDRESS_WIDTH=30, `else VIRTUAL_ADDRESS_WIDTH=PAW, `endif LGTLBSZ = 6, VAW=VIRTUAL_ADDRESS_WIDTH; localparam AW=ADDRESS_WIDTH; input wire i_clk, i_reset; // Wishbone master output wire o_wb_cyc, o_wb_stb, o_wb_we; output wire [(PAW-1):0] o_wb_addr; output wire [31:0] o_wb_data; output wire [3:0] o_wb_sel; input wire i_wb_ack, i_wb_stall; input wire [31:0] i_wb_data; input wire i_wb_err; // Incoming interrupts input wire i_ext_int; // Outgoing interrupt output wire o_ext_int; // Wishbone slave input wire i_dbg_cyc, i_dbg_stb, i_dbg_we, i_dbg_addr; input wire [31:0] i_dbg_data; output wire o_dbg_ack; output wire o_dbg_stall; output wire [31:0] o_dbg_data; // `ifdef DEBUG_SCOPE output wire [31:0] o_cpu_debug; `endif wire dbg_cyc, dbg_stb, dbg_we, dbg_addr, dbg_stall; wire [31:0] dbg_idata, dbg_odata; reg dbg_ack; assign dbg_cyc = i_dbg_cyc; assign dbg_stb = i_dbg_stb; assign dbg_we = i_dbg_we; assign dbg_addr = i_dbg_addr; assign dbg_idata = i_dbg_data; assign o_dbg_ack = dbg_ack; assign o_dbg_stall = dbg_stall; assign o_dbg_data = dbg_odata; // // The external debug interface // // We offer only a limited interface here, requiring a pre-register // write to set the local address. This interface allows access to // the Zip System on a debug basis only, and not to the rest of the // wishbone bus. Further, to access these registers, the control // register must first be accessed to both stop the CPU and to // set the following address in question. Hence all accesses require // two accesses: write the address to the control register (and halt // the CPU if not halted), then read/write the data from the data // register. // wire cpu_break, dbg_cmd_write; reg cmd_reset, cmd_halt, cmd_step, cmd_clear_pf_cache; reg [4:0] cmd_addr; wire [3:0] cpu_dbg_cc; assign dbg_cmd_write = (dbg_stb)&&(dbg_we)&&(!dbg_addr); // // Always start us off with an initial reset // initial cmd_reset = 1'b1; always @(posedge i_clk) cmd_reset <= ((dbg_cmd_write)&&(dbg_idata[`RESET_BIT])); // initial cmd_halt = START_HALTED; always @(posedge i_clk) if (i_reset) cmd_halt <= START_HALTED; else if (cmd_reset) cmd_halt <= START_HALTED; else if (dbg_cmd_write) cmd_halt <= ((dbg_idata[`HALT_BIT])&&(!dbg_idata[`STEP_BIT])); else if ((cmd_step)||(cpu_break)) cmd_halt <= 1'b1; initial cmd_clear_pf_cache = 1'b1; always @(posedge i_clk) cmd_clear_pf_cache <= (dbg_cmd_write)&&(dbg_idata[`CLEAR_CACHE_BIT]); // initial cmd_step = 1'b0; always @(posedge i_clk) cmd_step <= (dbg_cmd_write)&&(dbg_idata[`STEP_BIT]); // initial cmd_addr = 5'h0; always @(posedge i_clk) if (dbg_cmd_write) cmd_addr <= dbg_idata[4:0]; wire cpu_reset; assign cpu_reset = (cmd_reset); wire cpu_halt, cpu_dbg_stall; assign cpu_halt = (cmd_halt); wire [31:0] cmd_data; // Values: // 0x0003f -> cmd_addr mask // 0x00040 -> reset // 0x00080 -> PIC interrrupt pending // 0x00100 -> cmd_step // 0x00200 -> cmd_stall // 0x00400 -> cmd_halt // 0x00800 -> cmd_clear_pf_cache // 0x01000 -> cc.sleep // 0x02000 -> cc.gie // 0x10000 -> External interrupt line is high assign cmd_data = { 7'h00, 8'h00, i_ext_int, cpu_dbg_cc, 1'b0, cmd_halt, (!cpu_dbg_stall), 1'b0, i_ext_int, cpu_reset, 1'b0, cmd_addr }; // // The CPU itself // wire cpu_lcl_cyc, cpu_lcl_stb, cpu_dbg_we, cpu_op_stall, cpu_pf_stall, cpu_i_count; wire [31:0] cpu_dbg_data; assign cpu_dbg_we = ((dbg_stb)&&(dbg_we)&&(dbg_addr)); zipcpu #(.RESET_ADDRESS(RESET_ADDRESS), .ADDRESS_WIDTH(ADDRESS_WIDTH), .LGICACHE(LGICACHE), .WITH_LOCAL_BUS(0)) thecpu(i_clk, cpu_reset, i_ext_int, 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, o_wb_cyc, o_wb_stb, cpu_lcl_cyc, cpu_lcl_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)||(cpu_lcl_cyc), cpu_op_stall, cpu_pf_stall, cpu_i_count `ifdef DEBUG_SCOPE , o_cpu_debug `endif ); // Return debug response values assign dbg_odata = (!dbg_addr)?cmd_data :cpu_dbg_data; initial dbg_ack = 1'b0; always @(posedge i_clk) dbg_ack <= (dbg_stb)&&(!o_dbg_stall); assign dbg_stall= (cpu_dbg_stall)&&(dbg_addr); assign o_ext_int = (cmd_halt) && (!i_wb_stall); // Make Verilator happy // verilator lint_off UNUSED wire [4:0] unused; assign unused = { dbg_cyc, cpu_lcl_stb, cpu_op_stall, cpu_pf_stall, cpu_i_count }; // verilator lint_on UNUSED endmodule