This commit is contained in:
Philip Smart
2019-11-26 23:29:48 +00:00
parent 4dde157c8d
commit b41d5a97f0
67 changed files with 118001 additions and 119263 deletions

View File

@@ -47,6 +47,7 @@
-- 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.
-- 191126 v1.1 Bug fixes. When switching off WishBone the CPU wouldnt run.
--
library ieee;
@@ -520,8 +521,7 @@ begin
WB_INIT: if IMPL_USE_WB_BUS = true generate
--WB_CLK_I <= open;
ZPURESET <= RESET or WB_RST_I;
end generate;
NO_WB: if IMPL_USE_WB_BUS = false generate
else generate
ZPURESET <= RESET;
end generate;
@@ -575,11 +575,8 @@ begin
else '0';
cacheL2Empty <= '1' when cacheL2FetchIdx(ADDR_32BIT_RANGE) = cacheL2StartAddr(ADDR_32BIT_RANGE)
else '0';
cacheL2Invalid <= --'0' when pc(ADDR_32BIT_RANGE) >= cacheL2StartAddr(ADDR_32BIT_RANGE) and pc(ADDR_32BIT_RANGE) < cacheL2FetchIdx(ADDR_32BIT_RANGE)+64
'1' when pc(ADDR_32BIT_RANGE) < cacheL2StartAddr(ADDR_32BIT_RANGE) or (pc(ADDR_32BIT_RANGE) > cacheL2FetchIdx(ADDR_32BIT_RANGE))
-- or (pc(ADDR_32BIT_RANGE) = cacheL2StartAddr(ADDR_32BIT_RANGE) and cacheL2StartAddr(ADDR_32BIT_RANGE) = cacheL2FetchIdx(ADDR_32BIT_RANGE))) and cacheL2Active = '1'
cacheL2Invalid <= '1' when pc(ADDR_32BIT_RANGE) < cacheL2StartAddr(ADDR_32BIT_RANGE) or (pc(ADDR_32BIT_RANGE) > cacheL2FetchIdx(ADDR_32BIT_RANGE))
else '0';
--else '1';
cacheL2Mux2Addr <= cacheL1FetchIdx(L2CACHE_32BIT_RANGE) when DEBUG_CPU = false or (DEBUG_CPU = true and debugState = Debug_Idle)
else
debugPC(L2CACHE_32BIT_RANGE) when DEBUG_CPU = true
@@ -616,16 +613,14 @@ begin
MEM_WRITE_HWORD <= '0';
MEM_READ_ENABLE <= '0';
MEM_WRITE_ENABLE <= '0';
if IMPL_USE_WB_BUS = true then
WB_ADR_O(ADDR_32BIT_RANGE) <= (others => '0');
WB_DAT_O <= (others => '0');
WB_WE_O <= '0';
WB_CYC_O <= '0';
WB_STB_O <= '0';
WB_CTI_O <= "000";
WB_SEL_O <= "1111";
wbXactActive <= '0';
end if;
WB_ADR_O(ADDR_32BIT_RANGE) <= (others => '0');
WB_DAT_O <= (others => '0');
WB_WE_O <= '0';
WB_CYC_O <= '0';
WB_STB_O <= '0';
WB_CTI_O <= "000";
WB_SEL_O <= "1111";
wbXactActive <= '0';
cacheL2Write <= '0';
cacheL2IncAddr <= '0';
cacheL2FetchIdx <= (others => '0');
@@ -696,7 +691,7 @@ begin
end if;
-- If the external memory is busy (1) or the wishbone interface is active and no ACK received then we have to back off and wait till next clock cycle and check again.
if MEM_BUSY = '0' and (IMPL_USE_WB_BUS = true and ((wbXactActive = '1' and WB_ACK_I = '1') or wbXactActive = '0')) and mxHoldCycles = 0 then
if MEM_BUSY = '0' and ((IMPL_USE_WB_BUS = true and ((wbXactActive = '1' and WB_ACK_I = '1') or wbXactActive = '0')) or IMPL_USE_WB_BUS = false) and mxHoldCycles = 0 then
-- Memory transaction processor state machine. Idle is the control state and depending upon entries in the queue, debug or L2 usage, it
-- directs the FSM states accordingly.
@@ -958,7 +953,7 @@ begin
when MemXact_MemoryFetch =>
if DEBUG_CPU = true then
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxMemVal.word <= unsigned(WB_DAT_I);
else
mxMemVal.word <= unsigned(MEM_DATA_IN);
@@ -968,7 +963,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_OpcodeFetch =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
cacheL2WriteData <= WB_DAT_I;
else
cacheL2WriteData <= MEM_DATA_IN;
@@ -980,7 +975,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_TOS =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxTOS.word <= unsigned(WB_DAT_I);
else
mxTOS.word <= unsigned(MEM_DATA_IN);
@@ -989,7 +984,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_NOS =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxNOS.word <= unsigned(WB_DAT_I);
else
mxNOS.word <= unsigned(MEM_DATA_IN);
@@ -998,7 +993,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_TOSNOS =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxTOS.word <= unsigned(WB_DAT_I);
else
mxTOS.word <= unsigned(MEM_DATA_IN);
@@ -1028,7 +1023,7 @@ begin
end if;
when MemXact_TOSNOS_3 =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxNOS.word <= unsigned(WB_DAT_I);
mxNOS.valid <= '1';
mxFifoReadIdx <= mxFifoReadIdx + 1;
@@ -1048,7 +1043,7 @@ begin
when MemXact_ReadWordToTOS =>
mxTOS.word <= (others => '0');
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxTOS.word(15 downto 0) <= unsigned(WB_DAT_I(((wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16+15) downto (wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16));
else
mxTOS.word(15 downto 0) <= unsigned(MEM_DATA_IN(((wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16+15) downto (wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16));
@@ -1058,7 +1053,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_ReadAddToTOS =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
mxTOS.word <= muxTOS.word + unsigned(WB_DAT_I);
else
mxTOS.word <= muxTOS.word + unsigned(MEM_DATA_IN);
@@ -1067,7 +1062,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_WriteToAddr =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
WB_ADR_O(ADDR_32BIT_RANGE) <= WB_DAT_I(ADDR_32BIT_RANGE);
WB_ADR_O(minAddrBit-1 downto 0) <= (others => '0');
WB_DAT_O <= mxFifo(to_integer(mxFifoReadIdx)).data;
@@ -1097,7 +1092,7 @@ begin
when MemXact_WriteByteToAddr =>
-- For wishbone, we need to store the data and terminate the current cycle before we can commence a write cycle.
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
WB_DAT_O <= WB_DAT_I;
WB_DAT_O(((wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 0))))*8+7) downto (wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 0))))*8) <= std_logic_vector(mxFifo(to_integer(mxFifoReadIdx)).data(7 downto 0));
cacheL2WriteData <= WB_DAT_I;
@@ -1133,7 +1128,7 @@ begin
mxState <= MemXact_Idle;
when MemXact_WriteHWordToAddr =>
if wbXactActive = '1' then
if IMPL_USE_WB_BUS = true and wbXactActive = '1' then
WB_DAT_O <= WB_DAT_I;
WB_DAT_O(((wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16+15) downto (wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16) <= std_logic_vector(mxFifo(to_integer(mxFifoReadIdx)).data(15 downto 0));
cacheL2WriteData <= WB_DAT_I;
@@ -1145,8 +1140,8 @@ begin
MEM_DATA_OUT(((wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16+15) downto (wordBytes-1-to_integer(unsigned(mxFifo(to_integer(mxFifoReadIdx)).addr(byteBits-1 downto 1))))*16) <= std_logic_vector(mxFifo(to_integer(mxFifoReadIdx)).data(15 downto 0));
cacheL2WriteData <= MEM_DATA_IN;
MEM_WRITE_ENABLE <= '1';
mxFifoReadIdx <= mxFifoReadIdx + 1;
mxState <= MemXact_Idle;
mxFifoReadIdx <= mxFifoReadIdx + 1;
mxState <= MemXact_Idle;
end if;
-- If the data write is to a cached location, we have read the original value, so update cache with modified version.
if cacheL2MxAddrInCache = '1' then
@@ -1272,7 +1267,7 @@ begin
((cacheL2Active = '0' and MEM_BUSY_INSN = '0') or (cacheL2Active = '1'))
and
-- If using L2 cache then only process when cached data is available in L2.
(cacheL2Active = '0' or (cacheL2Active = '1' and cacheL2Empty = '0' and cacheL2Full = '1' and cacheL2FetchIdx(ADDR_32BIT_RANGE) > cacheL1FetchIdx(ADDR_32BIT_RANGE)+1 ))
(cacheL2Active = '0' or (cacheL2Active = '1' and cacheL2Empty = '0' and cacheL2FetchIdx(ADDR_32BIT_RANGE) > cacheL1FetchIdx(ADDR_32BIT_RANGE)+1 ))
and
-- If debugging, only process if the debug FSM is idle as the L2 address is muxed with the debug address.
((DEBUG_CPU = false or (DEBUG_CPU = true and debugState = Debug_Idle))) then
@@ -1626,7 +1621,7 @@ begin
end if;
-- Act immediately if an interrupt has occurred. Do not recurse into ISR while interrupt line is active
elsif (INT_REQ = '1' or WB_INTA_I = '1') and inInterrupt = '0' and idimFlag = '0' then
elsif (INT_REQ = '1' or (IMPL_USE_WB_BUS = true and WB_INTA_I = '1')) and inInterrupt = '0' and idimFlag = '0' then
-- We have to wait for TOS and NOS to become valid so they can be saved, so loop until they are valid.
if muxTOS.valid = '1' and muxNOS.valid = '1' then
@@ -1634,7 +1629,7 @@ begin
inInterrupt <= '1';
INT_ACK <= '1'; -- Acknowledge interrupt.
interruptSuspendedAddr <= pc(ADDR_BIT_RANGE); -- Save address which got interrupted.
-- TOS.word <= (others => DontCareValue);
-- TOS.word <= (others => DontCareValue);
TOS.word(ADDR_BIT_RANGE) <= pc;
NOS.word <= muxTOS.word;
pc <= to_unsigned(32+START_ADDR_MEM, maxAddrBit); -- Load Vector 0x20 (from memory start) as next address to execute from.
@@ -1683,7 +1678,7 @@ begin
state <= State_Idle;
-- Execution depends on the L1 having decoded instructions stored at the current PC.
-- As a minimum the cache must be valid and that there is at least 1 instructions in the cache.
-- As a minimum the cache must be valid and that there is at least 1 instruction in the cache.
elsif cacheL1Invalid = '0' and cacheL1InsnAfterPC > 4 then -- and (cacheL2Active = '0' or (cacheL2Active = '1' and cacheL2Full = '1')) then
-- Remember the last PC location executed, used for jump detection.
@@ -1903,7 +1898,7 @@ begin
tInsnExec := '1';
idimFlag <= '0';
sp <= decSp;
-- TOS.word <= (others => DontCareValue);
-- TOS.word <= (others => DontCareValue);
TOS.word(ADDR_BIT_RANGE) <= incPC;
NOS.word <= muxTOS.word;
@@ -1927,7 +1922,7 @@ begin
if muxTOS.valid = '1' and muxNOS.valid = '1' then
tInsnExec := '1';
idimFlag <= '0';
-- TOS.word <= (others => DontCareValue);
-- TOS.word <= (others => DontCareValue);
TOS.word(ADDR_BIT_RANGE) <= incPC;
pc <= pc + muxTOS.word(ADDR_BIT_RANGE);
end if;
@@ -1939,7 +1934,7 @@ begin
if muxTOS.valid = '1' and muxNOS.valid = '1' then
tInsnExec := '1';
idimFlag <= '0';
-- TOS.word <= (others => DontCareValue);
-- TOS.word <= (others => DontCareValue);
TOS.word(ADDR_BIT_RANGE) <= incPC;
pc <= muxTOS.word(ADDR_BIT_RANGE);
end if;
@@ -2750,7 +2745,7 @@ begin
debugRec.WRITE_STACK_TOS <= '1';
debugRec.WRITE_STACK_NOS <= '1';
debugRec.DATA(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(pc), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1FetchIdx), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1StartAddr), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1InsnAfterPC), 16));
debugRec.DATA2(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(cacheL2FetchIdx), 24)) & std_logic_vector(to_unsigned(to_integer(cacheL2StartAddr), 24)) & "10000000" & cacheL2IncAddr & idimFlag & tInsnExec & cacheL2Full & cacheL2Active & cacheL2Empty & cacheL2Write;
debugRec.DATA2(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(cacheL2FetchIdx), 24)) & std_logic_vector(to_unsigned(to_integer(cacheL2StartAddr), 24)) & "10000000" & '0' & cacheL2IncAddr & idimFlag & tInsnExec & cacheL2Full & cacheL2Active & cacheL2Empty & cacheL2Write;
debugRec.DATA3(63 downto 0) <= "00" & cacheL1(to_integer(pc))(DECODED_RANGE) & cacheL1(to_integer(pc))(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+1)(DECODED_RANGE) & cacheL1(to_integer(pc)+1)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+2)(DECODED_RANGE) & cacheL1(to_integer(pc)+2)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+3)(DECODED_RANGE) & cacheL1(to_integer(pc)+3)(OPCODE_RANGE);
debugRec.DATA4(63 downto 0) <= "00" & cacheL1(to_integer(pc)+4)(DECODED_RANGE) & cacheL1(to_integer(pc)+4)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+5)(DECODED_RANGE) & cacheL1(to_integer(pc)+5)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+6)(DECODED_RANGE) & cacheL1(to_integer(pc)+6)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+7)(DECODED_RANGE) & cacheL1(to_integer(pc)+7)(OPCODE_RANGE);
debugRec.OPCODE <= cacheL1(to_integer(pc))(OPCODE_RANGE);
@@ -2791,7 +2786,7 @@ begin
debugRec.WRITE_STACK_TOS <= '1';
debugRec.WRITE_STACK_NOS <= '1';
debugRec.DATA(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(pc), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1FetchIdx), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1StartAddr), 16)) & std_logic_vector(to_unsigned(to_integer(cacheL1InsnAfterPC), 16));
debugRec.DATA2(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(cacheL2FetchIdx), 24)) & std_logic_vector(to_unsigned(to_integer(cacheL2StartAddr), 24)) & "00000000" & cacheL2IncAddr & idimFlag & tInsnExec & cacheL2Full & cacheL2Active & cacheL2Empty & cacheL2Write;
debugRec.DATA2(63 downto 0) <= std_logic_vector(to_unsigned(to_integer(cacheL2FetchIdx), 24)) & std_logic_vector(to_unsigned(to_integer(cacheL2StartAddr), 24)) & "00000000" & '0' & cacheL2IncAddr & idimFlag & tInsnExec & cacheL2Full & cacheL2Active & cacheL2Empty & cacheL2Write;
debugRec.DATA3(63 downto 0) <= "00" & cacheL1(to_integer(pc))(DECODED_RANGE) & cacheL1(to_integer(pc))(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+1)(DECODED_RANGE) & cacheL1(to_integer(pc)+1)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+2)(DECODED_RANGE) & cacheL1(to_integer(pc)+2)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+3)(DECODED_RANGE) & cacheL1(to_integer(pc)+3)(OPCODE_RANGE);
debugRec.DATA4(63 downto 0) <= "00" & cacheL1(to_integer(pc)+4)(DECODED_RANGE) & cacheL1(to_integer(pc)+4)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+5)(DECODED_RANGE) & cacheL1(to_integer(pc)+5)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+6)(DECODED_RANGE) & cacheL1(to_integer(pc)+6)(OPCODE_RANGE) & "00" & cacheL1(to_integer(pc)+7)(DECODED_RANGE) & cacheL1(to_integer(pc)+7)(OPCODE_RANGE);
debugRec.OPCODE <= cacheL1(to_integer(pc))(OPCODE_RANGE);
@@ -3356,8 +3351,7 @@ begin
end if;
end if;
end process;
end generate;
NODIVIDER : if IMPL_DIV = false and IMPL_FIDIV32 = false and IMPL_MOD = false generate
else generate
dividendCopy <= (others => DontCareValue);
end generate;
@@ -3408,8 +3402,7 @@ begin
end if;
end if;
end process;
end generate;
NOFIADD32: if IMPL_FIADD32 = false generate
else generate
fpAddResult <= (others => DontCareValue);
end generate;
@@ -3479,8 +3472,7 @@ begin
fpMultResult(30 downto 0) <= result(30+quotientFractional downto quotientFractional);
end if;
end process;
end generate;
NOFIMULT32: if IMPL_FIMULT32 = false generate
else generate
fpMultResult <= (others => DontCareValue);
quotientFractional <= 0;
end generate;

View File

@@ -226,7 +226,7 @@ architecture behave of zpu_core_medium is
signal trace_topOfStack : std_logic_vector(WORD_32BIT_RANGE);
signal trace_topOfStackB : std_logic_vector(WORD_32BIT_RANGE);
signal clkDivider : unsigned(31 downto 0);
signal clkDivider : std_logic;
begin
@@ -302,7 +302,7 @@ begin
mem_writeMask <= (others => '1');
interrupt_ack <= '0';
interrupt_done <= '0';
clkDivider <= (others => '0');
clkDivider <= '0';
if DEBUG_CPU = true then
debugRec <= ZPU_DBG_T_INIT;
debugCnt <= 0;
@@ -337,9 +337,9 @@ begin
-- At the moment, the main state machine wont run at full (100MHz) speed, only 1/2 speed, hence the divider.
-- Once the delay causing it to fail is removed, freq reduced or re-engineered, remove this divider.
clkDivider <= clkDivider + 1;
if clkDivider(4) = '1' then
clkDivider <= (others => '0');
clkDivider <= '1';
if clkDivider = '1' then
clkDivider <= '0';
if DEBUG_CPU = false or (DEBUG_CPU = true and debugReady = '1') then
tCPURun := '1';
end if;
@@ -667,7 +667,7 @@ begin
when State_Execute =>
-- Debug code, if enabled, writes out the current instruction.
if DEBUG_CPU = true and insn /= State_InsnFetch then
if DEBUG_CPU = true and insn /= State_InsnFetch and pc >= X"9000" then
debugRec.FMT_DATA_PRTMODE <= "00";
debugRec.FMT_PRE_SPACE <= '0';
@@ -1150,7 +1150,7 @@ begin
state <= State_Decode;
-- If debug enabled, write out state during fetch.
if DEBUG_CPU = true then
if DEBUG_CPU = true and pc >= X"9000" then
debugRec.FMT_DATA_PRTMODE <= "00";
debugRec.FMT_PRE_SPACE <= '0';
debugRec.FMT_POST_SPACE <= '0';

View File

@@ -39,42 +39,16 @@ use ieee.numeric_std.all;
package zpu_pkg is
-- Constants common to all ZPU models source code.
constant Generate_Trace : boolean := false; -- generate trace output or not.
constant wordPower : integer := 5; -- The number of bits in a word, defined as 2^wordPower).
constant DontCareValue : std_logic := 'X'; -- during simulation, set this to '0' to get matching trace.txt
constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
constant wordSize : integer := 2**wordPower;
constant wordBytes : integer := wordSize/8;
constant minAddrBit : integer := byteBits;
constant WB_ACTIVE : integer := 1; -- Set to 1 if the wishbone interface is active to divide the address space in two, lower = direct access, upper = wishbone.
constant maxAddrBit : integer := 24 + WB_ACTIVE; -- Maximum address limit in bits.
constant maxAddrSize : integer := (2**maxAddrBit); -- Maximum address space size in bytes.
constant maxIOBit : integer := maxAddrBit - WB_ACTIVE - 4; -- Upper bit (to define range) of IO space in top section of address space.
-- constant maxMemBit : integer := 16; -- Non-EVO: Maximum memory bit, should be equal to maxAddrBit-1, Memory and IO each have 1/2 address space.
constant ioBit : integer := maxAddrBit - 1; -- Non-EVO: MSB is used to differentiate IO and memory.
constant ADDR_32BIT_SIZE : integer := maxAddrBit - minAddrBit; -- Bits in the address bus relevant for 32bit access.
constant WB_SELECT_BIT : integer := maxAddrBit - 1; -- Bit which divides the wishbone interface from normal memory space.
-- Ranges used throughout the SOC/ZPU source.
subtype ADDR_BIT_RANGE is natural range maxAddrBit-1 downto 0; -- Full address range - 1 byte aligned
subtype ADDR_16BIT_RANGE is natural range maxAddrBit-1 downto 1; -- Full address range - 2 bytes (16bit) aligned
subtype ADDR_32BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit; -- Full address range - 4 bytes (32bit) aligned
subtype ADDR_64BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit+1; -- Full address range - 8 bytes (64bit) aligned
-- subtype ADDR_MEM_32BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit; -- Non-EVO: Memory range.
subtype ADDR_IOBIT_RANGE is natural range ioBit downto minAddrBit; -- Non-EVO: IO range.
subtype WORD_32BIT_RANGE is natural range wordSize-1 downto 0; -- Number of bits in a word (normally 32 for this CPU).
subtype WORD_4BYTE_RANGE is natural range wordBytes-1 downto 0; -- Bits needed to represent wordSize in bytes (normally 4 for 32bits).
subtype BYTE_RANGE is natural range 7 downto 0; -- Number of bits in a byte.
-- Necessary functions for type conversion.
--
function bool_to_integer(level : boolean) return integer;
-- Evo specific options.
--
constant EVO_USE_INSN_BUS : boolean := true; -- Use a seperate instruction bus to connect to the BRAM memory. All other operations go over the normal bus.
constant EVO_USE_HW_BYTE_WRITE : boolean := true; -- Implement hardware writing of bytes, reads are always 32bit and aligned.
constant EVO_USE_HW_WORD_WRITE : boolean := true; -- Implement hardware writing of 16bit words, reads are always 32bit and aligned.
constant EVO_USE_WB_BUS : boolean := true; -- Implement the wishbone interface in addition to the standard direct interface. NB: Change WB_ACTIVE to 1 above if enabling.
constant EVO_USE_WB_BUS : boolean := false; -- Implement the wishbone interface in addition to the standard direct interface. NB: Change WB_ACTIVE to 1 above if enabling.
constant EVO_IMPL_RAM : boolean := true; -- Implement application RAM, seperate to the BRAM using BRAM. The main BRAM would then be just for initial boot up.
-- Debug options.
@@ -85,6 +59,34 @@ package zpu_pkg is
constant DEBUG_MAX_FIFO_BITS : integer := 3; -- Size of debug output data records fifo.
constant DEBUG_TX_BAUD_RATE : integer := 115200; --230400; -- Baud rate for the debug transmitter.
-- Constants common to all ZPU models source code.
constant Generate_Trace : boolean := false; -- generate trace output or not.
constant wordPower : integer := 5; -- The number of bits in a word, defined as 2^wordPower).
constant DontCareValue : std_logic := 'X'; -- during simulation, set this to '0' to get matching trace.txt
constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
constant wordSize : integer := 2**wordPower;
constant wordBytes : integer := wordSize/8;
constant minAddrBit : integer := byteBits;
constant WB_ACTIVE : integer := bool_to_integer(EVO_USE_WB_BUS); -- Set to 1 if the wishbone interface is active to divide the address space in two, lower = direct access, upper = wishbone.
constant maxAddrBit : integer := 24 + WB_ACTIVE; -- Maximum address limit in bits.
constant maxAddrSize : integer := (2**maxAddrBit); -- Maximum address space size in bytes.
constant maxIOBit : integer := maxAddrBit - WB_ACTIVE - 4; -- Upper bit (to define range) of IO space in top section of address space.
constant ioBit : integer := maxAddrBit - 1; -- Non-EVO: MSB is used to differentiate IO and memory.
constant ADDR_32BIT_SIZE : integer := maxAddrBit - minAddrBit; -- Bits in the address bus relevant for 32bit access.
constant WB_SELECT_BIT : integer := maxAddrBit - 1; -- Bit which divides the wishbone interface from normal memory space.
-- Ranges used throughout the SOC/ZPU source.
subtype ADDR_BIT_RANGE is natural range maxAddrBit-1 downto 0; -- Full address range - 1 byte aligned
subtype ADDR_16BIT_RANGE is natural range maxAddrBit-1 downto 1; -- Full address range - 2 bytes (16bit) aligned
subtype ADDR_32BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit; -- Full address range - 4 bytes (32bit) aligned
subtype ADDR_64BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit+1; -- Full address range - 8 bytes (64bit) aligned
-- subtype ADDR_MEM_32BIT_RANGE is natural range maxAddrBit-1 downto minAddrBit; -- Non-EVO: Memory range.
subtype ADDR_IOBIT_RANGE is natural range ioBit downto minAddrBit; -- Non-EVO: IO range.
subtype WORD_32BIT_RANGE is natural range wordSize-1 downto 0; -- Number of bits in a word (normally 32 for this CPU).
subtype WORD_4BYTE_RANGE is natural range wordBytes-1 downto 0; -- Bits needed to represent wordSize in bytes (normally 4 for 32bits).
subtype BYTE_RANGE is natural range 7 downto 0; -- Number of bits in a byte.
------------------------------------------------------------
-- components
------------------------------------------------------------
@@ -98,7 +100,7 @@ package zpu_pkg is
IMPL_CALL : boolean := true; -- Include call
IMPL_SHIFT : boolean := true; -- Include lshiftright, ashiftright and ashiftleft
IMPL_XOR : boolean := true; -- include xor instruction
CACHE : boolean := false;
CACHE : boolean := true;
CLK_FREQ : integer := 100000000; -- Frequency of the input clock.
STACK_ADDR : integer := 0 -- Initial stack address on CPU start.
);
@@ -226,9 +228,9 @@ package zpu_pkg is
IMPL_LOADB : boolean := true; -- Load single byte from memory.
IMPL_LOADH : boolean := true; -- Load half word (16bit) from memory.
IMPL_LSHIFTRIGHT : boolean := true; -- Logical shift right.
IMPL_MOD : boolean := false; -- 32bit modulo (remainder after division).
IMPL_MOD : boolean := true; -- 32bit modulo (remainder after division).
IMPL_MULT : boolean := true; -- 32bit signed multiplication.
IMPL_NEG : boolean := false; -- Negate value in TOS.
IMPL_NEG : boolean := true; -- Negate value in TOS.
IMPL_NEQ : boolean := true; -- Not equal test.
IMPL_POPPCREL : boolean := true; -- Pop a value into the Program Counter from a location relative to the Stack Pointer.
IMPL_PUSHSPADD : boolean := true; -- Add a value to the Stack pointer and push it onto the stack.
@@ -450,3 +452,18 @@ package zpu_pkg is
constant ZPU_DBG_T_INIT : zpu_dbg_t := ("00", '0', '0', '0', '0', (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0'));
constant ZPU_DBG_T_DONTCARE : zpu_dbg_t := ((others => DontCareValue), DontCareValue, DontCareValue, DontCareValue, DontCareValue, (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, DontCareValue, (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue), (others => DontCareValue));
end zpu_pkg;
package body zpu_pkg is
-- Helper to convert Boolean to integer.
--
function bool_to_integer(level : boolean) return integer is
begin
if level then
return(1);
else
return(0);
end if;
end function;
end package body zpu_pkg;