This commit is contained in:
Philip Smart
2019-10-23 14:14:42 +01:00
parent a580a78f23
commit 210cb9d974
12 changed files with 315 additions and 338 deletions

View File

@@ -359,5 +359,4 @@ set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulati
set_global_assignment -name SLD_FILE db/stp1_auto_stripped.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

Binary file not shown.

View File

@@ -34,14 +34,20 @@
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
--
-- History:
-- v0.1 Initial version created by merging items of the Small, Medium and Flex versions.
-- 181230
-- v0.5 Working with Instruction, Emulation or No Cache with or without seperate instruction
-- 190328 bus. Runs numerous tests and output same as the Medium CPU. One small issue is running
-- Evo History:
-- 181230 v0.1 Initial version created by merging items of the Small, Medium and Flex versions.
-- 190328 v0.5 Working with Instruction, Emulation or No Cache with or without seperate instruction
-- bus. Runs numerous tests and output same as the Medium CPU. One small issue is running
-- without an instruction bus and instruction/emulation cache enabled, the DMIPS value is lower
-- that just with instruction bus or emulation bus, seems some clash which reuults in waits states
-- slowing the CPU down.
-- 191021 v1.0 First release. All variations tested but more work needed on the SDRAM controller to
-- make use of burst mode in order to populate the L2 cache in fewer cycles.
-- Additional instructions need to be added back in after test and verification, albeit some
-- which are sepcific to the Sharp Emulator should be skipped.
-- Additional effort needs spending on the Wishbone Error signal to retry the bus transaction,
-- currently it just aborts it which is not ideal.
--
library ieee;
use ieee.std_logic_1164.all;
@@ -50,8 +56,12 @@ use ieee.numeric_std.all;
library work;
use work.zpu_pkg.all;
--------------------------------------------------------------------------------------------------------------------------------------------
-- ZPU Evo Signal Description.
--------------------------------------------------------------------------------------------------------------------------------------------
--
-- Main Memory/IO Bus.
-- -------------------
-- This bus is used to access all external memory and IO, it can also, via configuration, be used to read instructions from attahed memory.
--
-- MEM_WRITE_ENABLE - set to '1' for a single cycle to send off a write request.
@@ -69,7 +79,49 @@ use work.zpu_pkg.all;
-- MEM_READ_ENABLE='1' for a single cycle.
-- MEM_DATA_OUT - data to write
--
-- Wishbone Bus B4 Specification
-- -----------------------------
-- This bus is the industry standard for FPGA IP designs and the one primarily used in OpenCores. In this implementation it is
-- 32bit wide using a Master/Multi-Slave configuration with the ZPU acting as Master. It is a compile time configurable extension as
-- some uses of the ZPU Evo wont need it and thus saves fabric area. The description below is taken from the OpenCores Wishbone B4
-- specification.
--
-- WB_CLK_I - The clock input [WB_CLK_I] coordinates all activities for the internal logic within the WISHBONE interconnect.
-- - All WISHBONE output signals are registered at the rising edge of [WB_CLK_I]. All WISHBONE input signals are
-- - stable before the rising edge of [WB_CLK_I].
-- WB_RST_I - The reset input [WB_RST_I] forces the WISHBONE interface to restart. In this design, this signal is tied to the
-- - ZPU reset via an OR mechanism, forcing the ZPU to reset if activated.
-- WB_ACK_I - The acknowledge input [WB_ACK_I], when asserted, indicates the normal termination of a bus cycle.
-- WB_DAT_I - The data input array [WB_DAT_I] is used to pass binary data. The array boundaries are determined by the port size,
-- - with a port size of 32-bits in this design.
-- WB_DAT_O - The data output array [DAT_O()] is used to pass binary data. The array boundaries are determined by the port size,
-- - with a port size of 32-bits in this design.
-- WB_ADR_O - The address output array [WB_ADR_O] is used to pass a binary address. The higher array boundary is specific to the
-- - address width of the core, and the lower array boundary is determined by the data port size and granularity.
-- - This design is 32bit so WB_ADR[1:0] specify the byte level granularity.
-- WB_CYC_O - The cycle output [WB_CYC_O], when asserted, indicates that a valid bus cycle is in progress. The signal is asserted
-- - for the duration of all bus cycles.
-- WB_STB_O - The strobe output [WB_STB_O] indicates a valid data transfer cycle. It is used to qualify various other signals on
-- - the interface such as [WB_SEL_O]. The SLAVE asserts either the [WB_ACK_I], [WB_ERR_I] or [WB_RTY_I] signals in
-- - response to every assertion of the [WB_STB_O] signal.
-- WB_CTI_O - The Cycle Type Idenfier [WB_CTI_O] Address Tag provides additional information about the current cycle. The MASTER
-- - sends this information to the SLAVE. The SLAVE can use this information to prepare the response for the next cycle.
-- WB_WE_O - The write enable output [WB_WE_O] indicates whether the current local bus cycle is a READ or WRITE cycle. The
-- - signal is negated during READ cycles, and is asserted during WRITE cycles.
-- WB_SEL_O - The select output array [WB_SEL_O] indicates where valid data is expected on the [WB_DAT_I] signal array during
-- - READ cycles, and where it is placed on the [WB_DAT_O] signal array during WRITE cycles. The array boundaries are
-- - determined by the granularity of a port which is 32bit in this design leading to a WB_SEL_O width of 4 bits, 1
-- - bit to represent each byte. ie. WB_SEL_O[3] = MSB, WB_SEL_O[0] = LSB.
-- WB_HALT_I -
-- WB_ERR_I - The error input [WB_ERR_I] indicates an abnormal cycle termination. The source of the error, and the response
-- - generated by the MASTER is defined by the IP core supplier, in this case the intention (NYI) is to retry
-- - the transaction.
-- WB_INTA_I - A non standard signal to allow a wishbone device to interrupt the ZPU when set to logic '1'. The interrupt is
-- - registered on the next rising edge.
--
--
-- Instruction Memory Bus
-- ----------------------
-- This bus is used for dedicated faster response read only memory containing the code to be run. Using this bus results in faster
-- CPU performance. If this bus is not used/disabled, all instructions will be fetched via the main bus.
--
@@ -445,7 +497,7 @@ architecture behave of zpu_core_evo is
signal mxMemVal : WordRecord; -- Direct memory read result.
signal mxHoldCycles : integer range 0 to 3; -- Cycles to hold and extend memory transactions.
-- Debugging.
-- Hardware Debugging.
--
signal debugPC : unsigned(ADDR_BIT_RANGE); -- Debug PC for reading L1, L2 and memory for debugger output.
signal debugPC_StartAddr : unsigned(ADDR_BIT_RANGE); -- Start address for dump of memory contents.
@@ -478,7 +530,8 @@ begin
---------------------------------------------
-- Level 2 cache is instantiated rather than inferred. In Altera, numerous attempts failed at describing a cache with 1 write and 2 reads for inferrence
-- hence resorting to instantiating a defined IP component.
-- hence resorting to instantiating a defined IP component.
-- NB TODO: This needs to be split into a byte addressable IP so that L2 Cache Write Thru can work at byte/half-word level to increase througput.
CACHEL2 : dpram
generic map (
init_file => "",
@@ -544,10 +597,10 @@ begin
-- Memory transaction processor MXP.
------------------------------------
-- The mxp localises all memory/io operations into a single process. This aids in adaptation to differing bus topolgies as only this process
-- needs updating (the local INSN bus uses BRAM so direct connection). This logic processes a queue of transactions in fifo order and fetches instructions
-- as required.. The processor unit commits requests to the queue and this logic fulfills them. If the CPU is only using one bus for all memory and IO
-- operations then memory transactions in the queue are completed before instruction fetches. If the instruction queue is empty then the processor will
-- stall until instructions are fetched.
-- needs updating (the local INSN bus uses a direct BRAM/ROM connection and bypasses the MXP). This logic processes a queue of transactions in fifo
-- order and fetches instructions as required.. The processor unit commits requests to the queue and this logic fulfills them. If the CPU is only
-- using one bus for all memory and IO operations then memory transactions in the queue are completed before instruction fetches. If the instruction
-- queue is empty then the processor will stall until instructions are fetched.
--
MEMXACT: process(CLK, ZPURESET, TOS, NOS, debugState)
begin
@@ -625,7 +678,7 @@ begin
WB_STB_O <= '0';
end if;
-- WB_ERR_I needs handling.
-- TODO: WB_ERR_I needs better handling, should retry at least once and then issue a BREAK.
if IMPL_USE_WB_BUS = true and WB_ERR_I = '1' then
wbXactActive <= '0';
WB_CYC_O <= '0';
@@ -1131,12 +1184,8 @@ begin
cacheL2StartAddr <= cacheL2StartAddr + 16;
end if;
-- if pc(ADDR_32BIT_RANGE) > cacheL2FetchIdx(ADDR_32BIT_RANGE) and (pc(ADDR_32BIT_RANGE) - cacheL2FetchIdx(ADDR_32BIT_RANGE)) < 256 and cacheL2Full = '1' then
-- cacheL2StartAddr <= cacheL2StartAddr + 256;
-- end if;
-- If the PC goes out of scope of L2 data, reset and start fetching a fresh from the current PC address.
if cacheL2Invalid = '1' then --pc(ADDR_32BIT_RANGE) < cacheL2StartAddr(ADDR_32BIT_RANGE) or ((pc(ADDR_32BIT_RANGE) > cacheL2FetchIdx(ADDR_32BIT_RANGE))) then -- and (pc(ADDR_32BIT_RANGE) - cacheL2FetchIdx(ADDR_32BIT_RANGE)) >= 256) then
if cacheL2Invalid = '1' then
cacheL2FetchIdx <= pc(ADDR_32BIT_RANGE) & "00";
cacheL2StartAddr <= pc(ADDR_32BIT_RANGE) & "00";
cacheL2Write <= '0';
@@ -1145,10 +1194,6 @@ begin
mxState <= MemXact_Idle;
end if;
end if;
-- Do nothing if PC overshoots data we have fetched upto threshold, takes longer to reset and reread and then we waste potential instructions that will be jumped back to.
if pc(ADDR_32BIT_RANGE) >= cacheL2FetchIdx(ADDR_32BIT_RANGE) and (pc(ADDR_32BIT_RANGE) - cacheL2FetchIdx(ADDR_32BIT_RANGE)) < 512 then
end if;
end if;
end if;
end process;
@@ -1358,9 +1403,9 @@ begin
l1State <= State_PreSetAddr;
end case;
-- If there is only a set number of instructions remaining in the cache then we need to creeep the start address forward.
-- We do this to ensure as many past instructions are available for backward jumps which are most common in C. Adjust the threshold
-- if forward jumps are more common.
-- If there is only a set number of instructions remaining in the cache then we need to creep the start address forward so that
-- more instructions are fetched and decoded. We do this to ensure as many past instructions are available for backward jumps which
-- are most common in C. Adjust the threshold if forward jumps are more common.
elsif cacheL1InsnAfterPC < 8 and cacheL1Full = '1' then
cacheL1StartAddr <= cacheL1StartAddr + 8;
end if;
@@ -1724,10 +1769,11 @@ begin
debugRec.STACK_NOS <= std_logic_vector(muxNOS.word);
debugLoad <= '1';
end if;
--
-- USE cacheL1InsnAfterPC in this loop to preserve logic.
-- Same for extended instructions.
--
-- TODO:
-- Perhaps use cacheL1InsnAfterPC in this loop to preserve logic.
-- Same for extended instructions.
--
-- 5 Consecutive IM's
if cacheL1FetchIdx - pc > 5 and cacheL1(to_integer(pc))(7) = '1' and cacheL1(to_integer(pc)+1)(7) = '1' and cacheL1(to_integer(pc)+2)(7) = '1' and cacheL1(to_integer(pc)+3)(7) = '1' and cacheL1(to_integer(pc)+4)(7) = '1' and cacheL1(to_integer(pc)+5)(7) = '0' then
TOS.word(31 downto 0) <= unsigned(cacheL1(to_integer(pc))(3 downto 0)) & unsigned(cacheL1(to_integer(pc)+1)(OPCODE_IM_RANGE)) & unsigned(cacheL1(to_integer(pc)+2)(OPCODE_IM_RANGE)) & unsigned(cacheL1(to_integer(pc)+3)(OPCODE_IM_RANGE)) & unsigned(cacheL1(to_integer(pc)+4)(OPCODE_IM_RANGE));
@@ -2543,6 +2589,7 @@ begin
tInsnExec := '1';
-- For instructions which use a parameter, build the value ready for use.
-- TODO: This should be variables to meet the 1 cycle requirement or set during decode.
case cacheL1(to_integer(pc)+1)(OPCODE_PARAM_RANGE) is
when "00" => insnExParameter <= X"00000000";
when "01" => insnExParameter <= X"000000" & unsigned(cacheL1(to_integer(pc)+2)(OPCODE_RANGE));
@@ -2553,7 +2600,7 @@ begin
-- Decode the extended instruction at this point as we have access to 8 future instructions or bytes so can work out what is required and execute.
-- 1:0 = 00 means an instruction which operates with a default, byte, half-word or word parameter. ie. Extend,<insn>,[<byte>,<byte>,<byte>,<byte>]
-- Memory fill instruction. Fill memory starting at address in NOSwith zero, 8 bit, 16 or 32 bit repeating value for TOS bytes.
-- Memory fill instruction. Fill memory starting at address in NOS with zero, 8 bit, 16 or 32 bit repeating value for TOS bytes.
if cacheL1(to_integer(pc)+1)(OPCODE_INSN_RANGE) = Opcode_Ex_Fill then
end if;
@@ -2590,7 +2637,7 @@ begin
end if;
end if;
-- Breakpoint, this is not a mornal instruction and used by debuggers to suspend a program exection. At the moment
-- Breakpoint, this is not a nornal instruction and used by debuggers to suspend a program exection. At the moment
-- this instuction sets the BREAK flag and just continues.
when Insn_Break =>
tInsnExec := '1';
@@ -3202,7 +3249,6 @@ begin
debugRec.FMT_PRE_CR <= '1';
debugRec.FMT_SPLIT_DATA <= "01";
if debugPC = debugPC_EndAddr or debugPC_WidthCounter = debugPC_Width-4 then
--if debugPC = debugPC_EndAddr or debugPC = debugPC_WidthdebugPC(4 downto 2) = "111" then
debugRec.FMT_POST_CRLF <= '1';
debugPC_WidthCounter <= 0;
else

View File

@@ -117,7 +117,7 @@ package zpu_pkg is
--mem_writeMask
interrupt_request : in std_logic;
interrupt_ack : out std_logic; -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine.
interrupt_done : out std_logic; -- Interrupt service routine completed/done. : out std_logic_vector(wordBytes-1 downto 0);
interrupt_done : out std_logic; -- Interrupt service routine completed/done.
break : out std_logic;
debug_txd : out std_logic; -- Debug serial output.
--
@@ -287,8 +287,10 @@ package zpu_pkg is
INT_REQ : in std_logic;
INT_ACK : out std_logic; -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine.
INT_DONE : out std_logic; -- Interrupt service routine completed/done.
BREAK : out std_logic;
DEBUG_TXD : out std_logic -- Debug serial output.
-- Break and debug signals.
BREAK : out std_logic; -- A break instruction encountered.
CONTINUE : in std_logic; -- When break activated, processing stops. Setting CONTINUE to logic 1 resumes processing with next instruction.
DEBUG_TXD : out std_logic -- Debug serial output.
);
end component zpu_core_evo;
@@ -319,41 +321,6 @@ package zpu_pkg is
);
end component;
component signed_divider is
port (
clk : in std_logic;
ena : in std_logic;
z : in unsigned(63 downto 0);
d : in unsigned(WORD_32BIT_RANGE);
q : out signed(63 downto 0);
s : out signed(63 downto 0)
);
end component;
component unsigned_divider is
port (
clk : in std_logic;
ena : in std_logic;
z : in unsigned(63 downto 0);
d : in unsigned(WORD_32BIT_RANGE);
q : out unsigned(WORD_32BIT_RANGE);
s : out unsigned(WORD_32BIT_RANGE);
div0 : out std_logic;
ovf : out std_logic
);
end component;
component qdiv is
port (
dividend : in signed(WORD_32BIT_RANGE);
divisor : in signed(WORD_32BIT_RANGE);
start : in std_logic;
clk : in std_logic;
quotient_out : out signed(WORD_32BIT_RANGE);
complete : out std_logic
);
end component;
------------------------------------------------------------
-- constants
------------------------------------------------------------

View File

@@ -1,10 +1,40 @@
---------------------------------------------------------------------------------------------------------
--
-- Name: zpu_uart_debug.vhd
-- Created: January 2019
-- Author(s): Philip Smart
-- Description: An extension of the simplistic UART Tx, still fixed at 8N1 with configurable baud rate
-- but adding a debug serialisaztion FSM for output of ZPU runtime data.
-- Credits: Originally using the simplistic UART as a guide, which was written by the following
-- authors:-
-- Philippe Carton, philippe.carton2 libertysurf.fr
-- Juan Pablo Daniel Borgna, jpdborgna gmail.com
-- Salvador E. Tropea, salvador inti.gob.ar
-- Copyright: (c) 2019 Philip Smart <philip.smart@net2net.org>
--
-- History: January 2019 - Initial module written using the simplistic UART as a guide but
-- adding cache and debug serialisation FSM.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: 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 source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY 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. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
library ieee;
library pkgs;
library work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.zpu_pkg.all;
--use work.zpu_soc_pkg.all;
-- Based on the simplistic UART, handles 8N1 RS232 Rx/Tx with independent programmable baud rate and selectable FIFO buffers.
entity zpu_uart_debug is

View File

@@ -1,7 +1,7 @@
-- ZPU
--
-- Copyright 2004-2008 oharboe - <20>yvind Harboe - oyvind.harboe@zylin.com
-- Modified by Alastair M. Robinson for the ZPUFlex project.
-- Modified by Philip Smart 02/2019 for the ZPU Evo implementation.
--
-- The FreeBSD license
--

View File

@@ -2,7 +2,7 @@
--
-- Name: dpram.vhd
-- Created: January 2019
-- Author(s): Altera/Intel - refactored by Philip Smart for the ZPU Evo
-- Author(s): Altera/Intel Quartus II - refactored by Philip Smart for the ZPU Evo
-- Description: Dual Port RAM as provided by Altera in the Megafunctions suite.
--
-- Credits:
@@ -11,19 +11,6 @@
-- History: January 2019 - Initial module taken and refactored, customizing for the ZPU Evo.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: 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 source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY 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. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
@@ -164,6 +151,4 @@ BEGIN
q_b => sub_wire1
);
END SYN;

View File

@@ -1,6 +1,37 @@
-- Adapted by AMR from the Chameleon Minimig cfide.vhd file,
-- originally by Tobias Gubener.
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
--
--
-- spi_to_host contains data received from slave device.
-- Busy bit now has a signal of its own.

View File

@@ -1,3 +1,37 @@
-- 32bit prescaled Timer
--
-- Original Author unknown.
-- Updated for ZPU SoC use: Philip Smart, 2019.
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.ALL;
@@ -8,92 +42,90 @@ library work;
entity timer_controller is
generic(
prescale : integer := 1; -- Prescale incoming clock
timers : integer := 0 -- This is a power of 2, so zero means 1 counter, 4 means 16 counters...
);
prescale : integer := 1; -- Prescale incoming clock
timers : integer := 0 -- This is a power of 2, so zero means 1 counter, 4 means 16 counters...
);
port (
clk : in std_logic;
reset : in std_logic; -- active low
clk : in std_logic;
reset : in std_logic; -- active low
reg_addr_in : in std_logic_vector(7 downto 0); -- from host CPU
reg_data_in: in std_logic_vector(31 downto 0);
reg_rw : in std_logic;
reg_req : in std_logic;
reg_addr_in : in std_logic_vector(7 downto 0); -- from host CPU
reg_data_in : in std_logic_vector(31 downto 0);
reg_rw : in std_logic;
reg_req : in std_logic;
ticks : out std_logic_vector(2**timers-1 downto 0)
);
ticks : out std_logic_vector(2**timers-1 downto 0)
);
end entity;
architecture rtl of timer_controller is
constant prescale_adj : integer := prescale-1;
signal prescale_counter : unsigned(15 downto 0);
signal prescaled_tick : std_logic;
type timer_counters is array (2**timers-1 downto 0) of unsigned(31 downto 0);
signal timer_counter : timer_counters;
signal timer_limit : timer_counters;
signal timer_enabled : std_logic_vector(2**timers-1 downto 0);
signal timer_index : unsigned(7 downto 0);
constant prescale_adj : integer := prescale-1;
signal prescale_counter : unsigned(15 downto 0);
signal prescaled_tick : std_logic;
type timer_counters is array (2**timers-1 downto 0) of unsigned(31 downto 0);
signal timer_counter : timer_counters;
signal timer_limit : timer_counters;
signal timer_enabled : std_logic_vector(2**timers-1 downto 0);
signal timer_index : unsigned(7 downto 0);
begin
-- Prescaled tick
process(clk, reset)
begin
if reset='0' then
prescale_counter<=(others=>'0');
elsif rising_edge(clk) then
prescaled_tick<='0';
prescale_counter<=prescale_counter-1;
if prescale_counter=X"00" then
prescaled_tick<='1';
prescale_counter<=to_unsigned(prescale_adj,16);
end if;
end if;
end process;
-- Prescaled tick
process(clk, reset)
begin
if reset='0' then
prescale_counter <=(others => '0');
elsif rising_edge(clk) then
prescaled_tick <='0';
prescale_counter <=prescale_counter-1;
if prescale_counter=X"00" then
prescaled_tick <='1';
prescale_counter <=to_unsigned(prescale_adj,16);
end if;
end if;
end process;
-- The timers proper;
process(clk,reset)
begin
if reset='0' then
for I in 0 to (2**timers-1) loop
timer_counter(I)<=(others => '0');
end loop;
elsif rising_edge(clk) then
ticks<=(others => '0');
if prescaled_tick='1' then
for I in 0 to (2**timers-1) loop
if timer_enabled(I)='1' then
timer_counter(I)<=timer_counter(I)-1;
if timer_counter(I)=X"00000000" then
timer_counter(I)<=timer_limit(I);
ticks(I)<='1';
end if;
end if;
end loop;
end if;
end if;
end process;
-- The timers proper;
process(clk,reset)
begin
if reset='0' then
for I in 0 to (2**timers-1) loop
timer_counter(I) <= (others => '0');
end loop;
elsif rising_edge(clk) then
ticks <= (others => '0');
if prescaled_tick='1' then
for I in 0 to (2**timers-1) loop
if timer_enabled(I)='1' then
timer_counter(I) <=timer_counter(I)-1;
if timer_counter(I)=X"00000000" then
timer_counter(I)<=timer_limit(I);
ticks(I) <='1';
end if;
end if;
end loop;
end if;
end if;
end process;
-- Handle CPU access to hardware registers
process(clk,reset)
begin
if reset='0' then
timer_enabled<=(others => '0');
elsif rising_edge(clk) then
if reg_req='1' and reg_rw='0' then -- Write access
case reg_addr_in is
when X"00" =>
timer_enabled<=reg_data_in(2**timers-1 downto 0);
when X"04" =>
timer_index<=unsigned(reg_data_in(7 downto 0));
when X"08" =>
timer_limit(to_integer(timer_index(timers downto 0)))<=
unsigned(reg_data_in(31 downto 0));
when others =>
null;
end case;
end if;
end if;
end process;
-- Handle CPU access to hardware registers
process(clk,reset)
begin
if reset='0' then
timer_enabled <= (others => '0');
elsif rising_edge(clk) then
if reg_req='1' and reg_rw='0' then -- Write access
case reg_addr_in is
when X"00" =>
timer_enabled <= reg_data_in(2**timers-1 downto 0);
when X"04" =>
timer_index <= unsigned(reg_data_in(7 downto 0));
when X"08" =>
timer_limit(to_integer(timer_index(timers downto 0)))<= unsigned(reg_data_in(31 downto 0));
when others =>
null;
end case;
end if;
end if;
end process;
end architecture;

View File

@@ -2,10 +2,8 @@
--
-- Name: uart.vhd
-- Created: January 2019
-- Author(s): Philip Smart (based on the simplistic UART
-- Description: ZPU SOC IOCTL Interface to an Emulator (Sharp MZ series).
-- This module interfaces the ZPU IO processor to the Emulator IO Control backdoor
-- for updating ROM/RAM, OSD and providing IO services.
-- Author(s): Philip Smart
-- Description: A simplistic UART fixed at 8N1 but with configurable baud rate and RX/TX Fifoś.
-- Credits: Originally using the simplistic UART as a guide, which was written by the following
-- authors:-
-- Philippe Carton, philippe.carton2 libertysurf.fr

View File

@@ -4,8 +4,13 @@
-- Created: January 2019
-- Author(s): Philip Smart
-- Description: ZPU System On a Chip
--
-- This module contains the System on a Chip definition for the ZPU.
-- Itś purpose is to provide a functional eco-system around the ZPU to actually perform
-- real tasks. As a basic, boot and stack RAM, UART I/O and Timers are needed to at least
-- present a monitor via UART for interaction. Upon this can be added an SD card for
-- disk storage using the Fat FileSystem, SPI etc. Also, as the Wishbone interface is
-- used in the Evo CPU, any number of 3rd party device IP Cores can be added relatively
-- easily.
--
-- Credits:
-- Copyright: (c) 2018 Philip Smart <philip.smart@net2net.org>
@@ -530,7 +535,8 @@ begin
INT_REQ => INT_TRIGGER,
INT_ACK => INT_ACK, -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine.
INT_DONE => INT_DONE, -- Interrupt service routine completed/done.
BREAK => open,
BREAK => open, -- A break instruction encountered.
CONTINUE => '1', -- When break activated, processing stops. Setting CONTINUE to logic 1 resumes processing with next instruction.
DEBUG_TXD => UART2_TX -- Debug serial output.
);
end generate;
@@ -613,7 +619,8 @@ begin
INT_REQ => INT_TRIGGER,
INT_ACK => INT_ACK, -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine.
INT_DONE => INT_DONE, -- Interrupt service routine completed/done.
BREAK => open,
BREAK => open, -- A break instruction encountered.
CONTINUE => '1', -- When break activated, processing stops. Setting CONTINUE to logic 1 resumes processing with next instruction.
DEBUG_TXD => UART2_TX -- Debug serial output.
);
end generate;
@@ -647,34 +654,6 @@ begin
memBRead => BRAM_DATA_READ
);
end generate;
-- ZPUDPROMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_INSN_BRAM = true and SOC_IMPL_BRAM = true generate
-- ZPUROM : entity work.BootROM
-- port map (
-- clk => MEMCLK,
-- memAWriteEnable => BRAM_WREN,
-- memAAddr => MEM_ADDR(ADDR_BIT_BRAM_32BIT_RANGE),
-- memAWrite => MEM_DATA_WRITE,
-- memBWriteEnable => '0',
-- memBAddr => MEM_ADDR_INSN(ADDR_BIT_BRAM_32BIT_RANGE),
-- memBWrite => (others => '0'),
-- memARead => BRAM_DATA_READ,
-- memBRead => MEM_DATA_READ_INSN
-- );
-- end generate;
-- ZPUROMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_INSN_BRAM = false and SOC_IMPL_BRAM = true generate
-- ZPUROM : entity work.BootROM
-- port map (
-- clk => MEMCLK,
-- memAWriteEnable => BRAM_WREN,
-- memAAddr => MEM_ADDR(ADDR_BIT_BRAM_32BIT_RANGE),
-- memAWrite => MEM_DATA_WRITE,
-- memBWriteEnable => '0',
-- memBAddr => (others => 'X'),
-- memBWrite => (others => 'X'),
-- memARead => BRAM_DATA_READ,
-- memBRead => open
-- );
-- end generate;
-- Evo system BRAM, dual port to allow for seperate instruction bus read.
ZPUDPBRAMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_INSN_BRAM = true and SOC_IMPL_BRAM = true generate

View File

@@ -1,37 +1,31 @@
-- ZPU
---------------------------------------------------------------------------------------------------------
--
-- Copyright 2004-2008 oharboe - <20>yvind Harboe - oyvind.harboe@zylin.com
-- Copyright 2018-2019 psmart - Philip Smart
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
-- Name: zpu_soc_pkg.vhd
-- Created: January 2019
-- Author(s): Philip Smart
-- Description: ZPU System On a Chip Configuration
--
-- This module contains the System on a Chip configuration for the ZPU.
--
-- Credits:
-- Copyright: (c) 2018 Philip Smart <philip.smart@net2net.org>
--
-- History: January 2019 - Initial creation.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: 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 source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY 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. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
library ieee;
library pkgs;
@@ -130,16 +124,12 @@ package zpu_soc_pkg is
subtype IO_DECODE_RANGE is natural range maxAddrBit-WB_ACTIVE-1 downto maxIOBit; -- Upper bits in memory defining the IO block within the address space for the EVO cpu IO. All other models use ioBit.
-- subtype WB_IO_DECODE_RANGE is natural range maxAddrBit-1 downto maxIOBit; -- Upper bits in memory defining the IO block within the address space for the EVO cpu IO. All other models use ioBit.
-- Start byte address of stack for non-EVO CPU. Point to top of BRAM or a dedicated blcck of RAM - 2*words. Once booted the stack frame can be shifted to any memory location.
-- constant spStart : std_logic_vector(maxAddrBit-1 downto 0) := std_logic_vector(to_unsigned((2**(SOC_MAX_ADDR_BRAM_BIT))-8, maxAddrBit));
-- Device options
type CardType_t is (SD_CARD_E, SDHC_CARD_E); -- Define the different types of SD cards.
------------------------------------------------------------
-- constants
-- Constants
------------------------------------------------------------
constant YES : std_logic := '1';
@@ -151,17 +141,17 @@ package zpu_soc_pkg is
constant HIZ : std_logic := 'Z';
------------------------------------------------------------
-- functions
-- Function prototypes
------------------------------------------------------------
-- Find the maximum of two integers.
function IntMax(a : in integer; b : in integer) return integer;
------------------------------------------------------------
-- records
-- Records
------------------------------------------------------------
------------------------------------------------------------
-- components
-- Components
------------------------------------------------------------
component dualport_ram is
port (
@@ -177,24 +167,6 @@ package zpu_soc_pkg is
);
end component;
component cacheL2 is
generic (
MAX_CACHE_BITS : integer := 12
);
port (
clk : in std_logic;
areset : in std_logic := '0';
memAWriteEnable : in std_logic;
memAAddr : in std_logic_vector(MAX_CACHE_BITS-3 downto 0);
memAWrite : in std_logic_vector(55 downto 0);
memBWriteEnable : in std_logic;
memBAddr : in std_logic_vector(MAX_CACHE_BITS-3 downto 0);
memBWrite : in std_logic_vector(55 downto 0);
memARead : out std_logic_vector(55 downto 0);
memBRead : out std_logic_vector(55 downto 0)
);
end component;
component dpram
generic (
init_file : string;
@@ -222,41 +194,6 @@ package zpu_soc_pkg is
);
end component;
component signed_divider is
port (
clk : in std_logic;
ena : in std_logic;
z : in unsigned(63 downto 0);
d : in unsigned(WORD_32BIT_RANGE);
q : out signed(63 downto 0);
s : out signed(63 downto 0)
);
end component;
component unsigned_divider is
port (
clk : in std_logic;
ena : in std_logic;
z : in unsigned(63 downto 0);
d : in unsigned(WORD_32BIT_RANGE);
q : out unsigned(WORD_32BIT_RANGE);
s : out unsigned(WORD_32BIT_RANGE);
div0 : out std_logic;
ovf : out std_logic
);
end component;
component qdiv is
port (
dividend : in signed(WORD_32BIT_RANGE);
divisor : in signed(WORD_32BIT_RANGE);
start : in std_logic;
clk : in std_logic;
quotient_out : out signed(WORD_32BIT_RANGE);
complete : out std_logic
);
end component;
component SDCard is
generic (
FREQ_G : real := 100.0; -- Master clock frequency (MHz).
@@ -287,49 +224,22 @@ package zpu_soc_pkg is
);
end component;
component sdram_v is
port (
-- interface to the MT48LC16M16 chip
sd_clk : in std_logic; -- sdram is accessed at 128MHz
sd_rst : in std_logic; -- reset the sdram controller.
sd_cke : out std_logic; -- clock enable.
sd_dq : inout std_logic_vector(15 downto 0); -- 16 bit bidirectional data bus
sd_addr : out std_logic_vector(12 downto 0); -- 13 bit multiplexed address bus
sd_dqm : out std_logic_vector(1 downto 0); -- two byte masks
sd_ba : out std_logic_vector(1 downto 0); -- two banks
sd_cs_n : out std_logic; -- a single chip select
sd_we_n : out std_logic; -- write enable
sd_ras_n : out std_logic; -- row address select
sd_cas_n : out std_logic; -- columns address select
sd_ready : out std_logic; -- sd ready.
-- cpu/chipset interface
wb_clk : in std_logic; -- 32MHz chipset clock to which sdram state machine is synchonized
wb_dat_i : in std_logic_vector(31 downto 0); -- data input from chipset/cpu
wb_dat_o : out std_logic_vector(31 downto 0); -- data output to chipset/cpu
wb_ack : out std_logic;
wb_adr : in std_logic_vector(23 downto 0); -- lower 2 bits are ignored.
wb_sel : in std_logic_vector(3 downto 0);
wb_cti : in std_logic_vector(2 downto 0); -- cycle type.
wb_stb : in std_logic;
wb_cyc : in std_logic; -- cpu/chipset requests cycle
wb_we : in std_logic -- cpu/chipset requests write
);
end component;
end zpu_soc_pkg;
------------------------------------------------------------
-- Function definitions.
------------------------------------------------------------
package body zpu_soc_pkg is
-- Find the maximum of two integers.
function IntMax(a : in integer; b : in integer) return integer is
begin
if a > b then
return a;
else
return b;
end if;
return a;
end function IntMax;
-- Find the maximum of two integers.
function IntMax(a : in integer; b : in integer) return integer is
begin
if a > b then
return a;
else
return b;
end if;
return a;
end function IntMax;
end package body;