--------------------------------------------------------------------------------------------------------- -- -- Name: zpu_soc.vhd -- 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 -- -- 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 . --------------------------------------------------------------------------------------------------------- library ieee; library pkgs; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.zpu_soc_pkg.all; use work.zpu_pkg.all; entity zpu_soc is generic ( SYSCLK_FREQUENCY : integer := SYSTEM_FREQUENCY -- System clock frequency ); port ( -- Global Control -- SYSCLK : in std_logic; -- System clock, running at frequency indicated in SYSCLK_FREQUENCY MEMCLK : in std_logic; -- Memory clock, running at twice frequency indicated in SYSCLK_FREQUENCY RESET_IN : in std_logic; -- UART 0 & 1 UART_RX_0 : in std_logic; UART_TX_0 : out std_logic; UART_RX_1 : in std_logic; UART_TX_1 : out std_logic; -- SPI signals SPI_MISO : in std_logic := '1'; -- Allow the SPI interface not to be plumbed in. SPI_MOSI : out std_logic; SPI_CLK : out std_logic; SPI_CS : out std_logic; -- SD Card (SPI) signals SDCARD_MISO : in std_logic_vector(SOC_SD_DEVICES-1 downto 0) := (others => '1'); SDCARD_MOSI : out std_logic_vector(SOC_SD_DEVICES-1 downto 0); SDCARD_CLK : out std_logic_vector(SOC_SD_DEVICES-1 downto 0); SDCARD_CS : out std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- PS/2 signals PS2K_CLK_IN : in std_logic := '1'; PS2K_DAT_IN : in std_logic := '1'; PS2K_CLK_OUT : out std_logic; PS2K_DAT_OUT : out std_logic; PS2M_CLK_IN : in std_logic := '1'; PS2M_DAT_IN : in std_logic := '1'; PS2M_CLK_OUT : out std_logic; PS2M_DAT_OUT : out std_logic; -- I²C signals I2C_SCL_IO : inout std_logic; I2C_SDA_IO : inout std_logic; -- IOCTL Bus IOCTL_DOWNLOAD : out std_logic; -- Downloading to FPGA. IOCTL_UPLOAD : out std_logic; -- Uploading from FPGA. IOCTL_CLK : out std_logic; -- I/O Clock. IOCTL_WR : out std_logic; -- Write Enable to FPGA. IOCTL_RD : out std_logic; -- Read Enable from FPGA. IOCTL_SENSE : in std_logic; -- Sense to see if HPS accessing ioctl bus. IOCTL_SELECT : out std_logic; -- Enable IOP control over ioctl bus. IOCTL_ADDR : out std_logic_vector(24 downto 0); -- Address in FPGA to write into. IOCTL_DOUT : out std_logic_vector(31 downto 0); -- Data to be written into FPGA. IOCTL_DIN : in std_logic_vector(31 downto 0); -- Data to be read into HPS. -- SDRAM signals SDRAM_CLK : out std_logic; -- sdram is accessed at 100MHz SDRAM_CKE : out std_logic; -- clock enable. SDRAM_DQ : inout std_logic_vector(15 downto 0); -- 16 bit bidirectional data bus SDRAM_ADDR : out std_logic_vector(11 downto 0); -- 12 bit multiplexed address bus SDRAM_DQM : out std_logic_vector(1 downto 0); -- two byte masks SDRAM_BA : out std_logic_vector(1 downto 0); -- two banks SDRAM_CS_n : out std_logic; -- a single chip select SDRAM_WE_n : out std_logic; -- write enable SDRAM_RAS_n : out std_logic; -- row address select SDRAM_CAS_n : out std_logic; -- columns address select SDRAM_READY : out std_logic -- sd ready. -- DDR2 DRAM --DDR2_ADDR : out std_logic_vector(13 downto 0); -- 14 bit multiplexed address bus --DDR2_DQ : inout std_logic_vector(63 downto 0); -- 64 bit bidirectional data bus --DDR2_DQS : inout std_logic_vector(7 downto 0); -- 8 bit bidirectional data bus --DDR2_DQM : out std_logic_vector(17 downto 0); -- eight byte masks --DDR2_ODT : out std_logic_vector(1 downto 0); -- 14 bit multiplexed address bus --DDR2_BA : out std_logic_vector(2 downto 0); -- 8 banks --DDR2_CS : out std_logic_vector(1 downto 0); -- 2 chip selects. --DDR2_WE : out std_logic; -- write enable --DDR2_RAS : out std_logic; -- row address select --DDR2_CAS : out std_logic; -- columns address select --DDR2_CKE : out std_logic_vector(1 downto 0); -- 2 clock enable. --DDR2_CLK : out std_logic_vector(1 downto 0) -- 2 clocks. ); end entity; architecture rtl of zpu_soc is -- FSM States for the SD card to interface with the controller. type SDStateType is ( SD_STATE_IDLE, SD_STATE_RESET, SD_STATE_RESET_1, SD_STATE_WRITE, SD_STATE_WRITE_1, SD_STATE_WRITE_2, SD_STATE_READ, SD_STATE_READ_1, SD_STATE_READ_2 ); -- Reset processing. signal RESET_n : std_logic := '0'; signal RESET_COUNTER : unsigned(15 downto 0); signal RESET_COUNTER_RX : unsigned(15 downto 0); -- Millisecond counter signal MICROSEC_DOWN_COUNTER : unsigned(23 downto 0); -- Allow for 16 seconds delay. signal MILLISEC_DOWN_COUNTER : unsigned(17 downto 0); -- Allow for 262 seconds delay. signal MILLISEC_UP_COUNTER : unsigned(31 downto 0); -- Up counter allowing for 49 days count in milliseconds. signal SECOND_DOWN_COUNTER : unsigned(11 downto 0); -- Allow for 1 hour in seconds delay. signal MICROSEC_DOWN_TICK : integer range 0 to 150; -- Independent tick register to ensure down counter is accurate. signal MILLISEC_DOWN_TICK : integer range 0 to 150*1000; -- Independent tick register to ensure down counter is accurate. signal SECOND_DOWN_TICK : integer range 0 to 150*1000000; -- Independent tick register to ensure down counter is accurate. signal MILLISEC_UP_TICK : integer range 0 to 150*1000; -- Independent tick register to ensure up counter is accurate. signal MICROSEC_DOWN_INTR : std_logic; -- Interrupt when counter reaches 0. signal MICROSEC_DOWN_INTR_EN : std_logic; -- Interrupt enable for microsecond down counter. signal MILLISEC_DOWN_INTR : std_logic; -- Interrupt when counter reaches 0. signal MILLISEC_DOWN_INTR_EN : std_logic; -- Interrupt enable for millisecond down counter. signal SECOND_DOWN_INTR : std_logic; -- Interrupt when counter reaches 0. signal SECOND_DOWN_INTR_EN : std_logic; -- Interrupt enable for second down counter. signal RTC_MICROSEC_TICK : integer range 0 to 150; -- Allow for frequencies upto 150MHz. signal RTC_MICROSEC_COUNTER : integer range 0 to 1000; -- Real Time Clock counters. signal RTC_MILLISEC_COUNTER : integer range 0 to 1000; signal RTC_SECOND_COUNTER : integer range 0 to 60; signal RTC_MINUTE_COUNTER : integer range 0 to 60; signal RTC_HOUR_COUNTER : integer range 0 to 24; signal RTC_DAY_COUNTER : integer range 1 to 32; signal RTC_MONTH_COUNTER : integer range 1 to 13; signal RTC_YEAR_COUNTER : integer range 0 to 4095; signal RTC_TICK_HALT : std_logic; -- Timer register block signals signal TIMER_REG_REQ : std_logic; signal TIMER1_TICK : std_logic; -- SPI Clock counter signal SPI_TICK : unsigned(8 downto 0); signal SPICLK_IN : std_logic; signal SPI_FAST : std_logic; -- SPI signals signal HOST_TO_SPI : std_logic_vector(7 downto 0); signal SPI_TO_HOST : std_logic_vector(31 downto 0); signal SPI_WIDE : std_logic; signal SPI_TRIGGER : std_logic; signal SPI_BUSY : std_logic; signal SPI_ACTIVE : std_logic; -- SD Card signals type SDAddrArray is array(natural range 0 to SOC_SD_DEVICES-1) of std_logic_vector(WORD_32BIT_RANGE); type SDDataArray is array(natural range 0 to SOC_SD_DEVICES-1) of std_logic_vector(7 downto 0); type SDErrorArray is array(natural range 0 to SOC_SD_DEVICES-1) of std_logic_vector(15 downto 0); -- signal SD_RESET : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- active-high, synchronous reset. signal SD_RD : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- active-high read block request. signal SD_WR : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- active-high write block request. signal SD_CONTINUE : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- If true, inc address and continue R/W. signal SD_CARD_TYPE : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- Type of card, 0 = SD, 1 = SDHC signal SD_ADDR : SDAddrArray; -- Block address. signal SD_DATA_READ : SDDataArray; -- Data read from block. signal SD_DATA_WRITE : std_logic_vector(7 downto 0); -- Data byte to write to block. signal SD_DATA_VALID : std_logic; -- Flag to indicate when data has been received (rx). signal SD_DATA_REQ : std_logic; -- Flag to indicate when data is valid for tx. signal SD_CHANNEL : integer range 0 to SOC_SD_DEVICES-1; -- Active channel in the state machine. signal SD_BUSY : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- High when controller is busy performing some operation. signal SD_HNDSHK_IN : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- High when host has data to give or has taken data. signal SD_HNDSHK_OUT : std_logic_vector(SOC_SD_DEVICES-1 downto 0); -- High when controller has taken data or has data to give. signal SD_ERROR : SDErrorArray; -- Card error occurred (1). signal SD_OVERRUN : std_logic; -- Receive data overrun flag. signal SD_STATE : SDStateType; -- State machine states. signal SD_RESET_TIMER : integer range 0 to 100; -- 100ns reset timer, allows for SYSFREQ = 10 .. 100MHz. -- UART signals signal UART0_WR : std_logic; signal UART0_ADDR : std_logic; signal UART0_DATA_OUT : std_logic_vector(31 downto 0); signal UART0_TX_INTR : std_logic; signal UART0_RX_INTR : std_logic; signal UART1_WR : std_logic; signal UART1_ADDR : std_logic; signal UART1_DATA_OUT : std_logic_vector(31 downto 0); signal UART1_TX_INTR : std_logic; signal UART1_RX_INTR : std_logic; signal UART1_TX : std_logic; signal UART2_TX : std_logic; -- PS2 signals signal PS2_INT : std_logic; -- PS2 Keyboard Signals. signal KBD_IDLE : std_logic; signal KBD_RECV : std_logic; signal KBD_RECV_REG : std_logic; signal KBD_SEND_BUSY : std_logic; signal KBD_SEND_TRIGGER : std_logic; signal KBD_SEND_DONE : std_logic; signal KBD_SEND_BYTE : std_logic_vector(7 downto 0); signal KBD_RECV_BYTE : std_logic_vector(10 downto 0); -- I²C Signals. signal SCL_PAD_IN : std_logic; -- i2c clock line input signal SCL_PAD_OUT : std_logic; -- i2c clock line output signal SCL_PAD_OE : std_logic; -- i2c clock line output enable, active low signal SDA_PAD_IN : std_logic; -- i2c data line input signal SDA_PAD_OUT : std_logic; -- i2c data line output signal SDA_PAD_OE : std_logic; -- i2c data line output enable, active low signal WB_DATA_READ_I2C : std_logic_vector(WORD_32BIT_RANGE); -- i2c data as 32bit word for placing on WB bus. signal WB_I2C_ACK : std_logic; signal WB_I2C_HALT : std_logic; signal WB_I2C_ERR : std_logic; signal WB_I2C_CS : std_logic; signal WB_I2C_IRQ : std_logic; -- Wishbone control signals. signal WB_SDRAM_ACK : std_logic; signal WB_SDRAM_STB : std_logic; signal WB_DATA_READ_SDRAM : std_logic_vector(WORD_32BIT_RANGE); signal WB_SDRAM_SELECT : std_logic; signal WB_SDRAM_WREN : std_logic; -- ZPU signals signal MEM_BUSY : std_logic; signal IO_WAIT_SD : std_logic; signal IO_WAIT_SPI : std_logic; signal IO_WAIT_PS2 : std_logic; signal IO_WAIT_INTR : std_logic; signal IO_WAIT_TIMER1 : std_logic; signal IO_WAIT_IOCTL : std_logic; signal MEM_DATA_READ : std_logic_vector(WORD_32BIT_RANGE); signal MEM_DATA_WRITE : std_logic_vector(WORD_32BIT_RANGE); signal MEM_ADDR : std_logic_vector(ADDR_BIT_RANGE); signal MEM_WRITE_ENABLE : std_logic; signal MEM_WRITE_BYTE_ENABLE : std_logic; signal MEM_WRITE_HWORD_ENABLE : std_logic; signal MEM_READ_ENABLE : std_logic; signal MEM_READ_ENABLE_LAST : std_logic; signal MEM_DATA_READ_INSN : std_logic_vector(WORD_64BIT_RANGE); signal MEM_ADDR_INSN : std_logic_vector(ADDR_BIT_RANGE); signal MEM_READ_ENABLE_INSN : std_logic; signal IO_DATA_READ : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_SPI : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_SD : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_PS2 : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_INTRCTL : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_SOCCFG : std_logic_vector(WORD_32BIT_RANGE); signal IO_DATA_READ_IOCTL : std_logic_vector(WORD_32BIT_RANGE); -- ZPU ROM/BRAM/RAM/Stack signals. signal MEM_A_WRITE_ENABLE : std_logic; signal MEM_A_ADDR : std_logic_vector(ADDR_32BIT_RANGE); signal MEM_A_WRITE : std_logic_vector(WORD_32BIT_RANGE); signal MEM_B_WRITE_ENABLE : std_logic; signal MEM_B_ADDR : std_logic_vector(ADDR_32BIT_RANGE); signal MEM_B_WRITE : std_logic_vector(WORD_32BIT_RANGE); signal MEM_A_READ : std_logic_vector(WORD_32BIT_RANGE); signal MEM_B_READ : std_logic_vector(WORD_32BIT_RANGE); -- Master Wishbone Memory/IO bus interface. signal WB_CLK_I : std_logic; signal WB_RST_I : std_logic; signal WB_ACK_I : std_logic; signal WB_DAT_I : std_logic_vector(WORD_32BIT_RANGE); signal WB_DAT_O : std_logic_vector(WORD_32BIT_RANGE); signal WB_ADR_O : std_logic_vector(ADDR_BIT_RANGE); signal WB_CYC_O : std_logic; signal WB_STB_O : std_logic; signal WB_CTI_O : std_logic_vector(2 downto 0); signal WB_WE_O : std_logic; signal WB_SEL_O : std_logic_vector(WORD_4BYTE_RANGE); signal WB_HALT_I : std_logic; signal WB_ERR_I : std_logic; signal WB_INTA_I : std_logic; -- Interrupt signals signal INT_TRIGGERS : std_logic_vector(SOC_INTR_MAX downto 0); signal INT_ENABLE : std_logic_vector(SOC_INTR_MAX downto 0); signal INT_STATUS : std_logic_vector(SOC_INTR_MAX downto 0); signal INT_REQ : std_logic; signal INT_TRIGGER : std_logic; signal INT_ACK : std_logic; signal INT_DONE : std_logic; -- ZPU ROM/BRAM/RAM signal BRAM_SELECT : std_logic; signal RAM_SELECT : std_logic; signal SDRAM_SELECT : std_logic; signal BRAM_WREN : std_logic; signal RAM_WREN : std_logic; signal SDRAM_WREN : std_logic; signal SDRAM_RDEN : std_logic; signal SDRAM_MEM_BUSY : std_logic; signal BRAM_DATA_READ : std_logic_vector(WORD_32BIT_RANGE); signal RAM_DATA_READ : std_logic_vector(WORD_32BIT_RANGE); signal SDRAM_DATA_READ : std_logic_vector(WORD_32BIT_RANGE); -- IOCTL signal IOCTL_RDINT : std_logic; signal IOCTL_WRINT : std_logic; signal IOCTL_DATA_OUT : std_logic_vector(31 downto 0); -- IO Chip selects signal IO_SELECT : std_logic; -- IO Range 0x7FFFFxxx of devices connected to the ZPU system bus. signal WB_IO_SELECT : std_logic; -- IO Range of the ZPU CPU 0xF00000 .. 0xFFFFFF signal WB_IO_SOC_SELECT : std_logic; -- IO Range used within the SoC for small devices, upto 256 locations per device. 0x1F000xx signal IO_UART_SELECT : std_logic; -- Uart Range 0xFFFFFAxx signal IO_INTR_SELECT : std_logic; -- Interrupt Range 0xFFFFFBxx signal IO_TIMER_SELECT : std_logic; -- Timer Range 0xFFFFFCxx signal IO_SPI_SELECT : std_logic; -- SPI Range 0xFFFFFDxx signal IO_PS2_SELECT : std_logic; -- PS2 Range 0xFFFFFExx signal IOCTL_CS : std_logic; -- 0x800-80F signal SD_CS : std_logic; -- 0x900-93F signal UART0_CS : std_logic; -- 0xA00-C0F signal UART1_CS : std_logic; -- 0xA10-A1F signal INTR0_CS : std_logic; -- 0xB00-B0F signal TIMER0_CS : std_logic; -- 0xC00-C0F Millisecond timer. signal TIMER1_CS : std_logic; -- 0xC10-C1F signal SPI0_CS : std_logic; -- 0xD00-D0F signal PS2_CS : std_logic; -- 0xE00-E0F signal SOCCFG_CS : std_logic; -- 0xF00-F0F function to_std_logic(L: boolean) return std_logic is begin if L then return('1'); else return('0'); end if; end function to_std_logic; begin -- -- Instantiation -- -- Main CPU ZPUFLEX: if ZPU_FLEX = 1 generate ZPU0 : zpu_core_flex generic map ( IMPL_MULTIPLY => true, IMPL_COMPARISON_SUB => true, IMPL_EQBRANCH => true, IMPL_STOREBH => false, IMPL_LOADBH => false, IMPL_CALL => true, IMPL_SHIFT => true, IMPL_XOR => true, CACHE => true, -- IMPL_EMULATION => minimal, -- REMAP_STACK => false --true, -- We need to remap the Boot ROM / Stack RAM so we can access SDRAM CLK_FREQ => SYSCLK_FREQUENCY, STACK_ADDR => SOC_STACK_ADDR -- Initial stack address on CPU start. ) port map ( clk => SYSCLK, reset => not RESET_n, enable => '1', in_mem_busy => MEM_BUSY, mem_read => MEM_DATA_READ, mem_write => MEM_DATA_WRITE, out_mem_addr => MEM_ADDR, out_mem_writeEnable => MEM_WRITE_ENABLE, out_mem_hEnable => MEM_WRITE_HWORD_ENABLE, out_mem_bEnable => MEM_WRITE_BYTE_ENABLE, out_mem_readEnable => MEM_READ_ENABLE, interrupt_request => INT_TRIGGER, interrupt_ack => INT_ACK, -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine. interrupt_done => INT_DONE, -- Interrupt service routine completed/done. break => open, debug_txd => UART2_TX, -- Debug serial output. -- MEM_A_WRITE_ENABLE => MEM_A_WRITE_ENABLE, MEM_A_ADDR => MEM_A_ADDR, MEM_A_WRITE => MEM_A_WRITE, MEM_B_WRITE_ENABLE => MEM_B_WRITE_ENABLE, MEM_B_ADDR => MEM_B_ADDR, MEM_B_WRITE => MEM_B_WRITE, MEM_A_READ => MEM_A_READ, MEM_B_READ => MEM_B_READ ); end generate; ZPUSMALL: if ZPU_SMALL = 1 generate ZPU0 : zpu_core_small generic map ( CLK_FREQ => SYSCLK_FREQUENCY, STACK_ADDR => SOC_STACK_ADDR -- Initial stack address on CPU start. ) port map ( clk => SYSCLK, areset => not RESET_n, enable => '1', in_mem_busy => MEM_BUSY, mem_read => MEM_DATA_READ, mem_write => MEM_DATA_WRITE, out_mem_addr => MEM_ADDR, out_mem_writeEnable => MEM_WRITE_ENABLE, out_mem_hEnable => MEM_WRITE_HWORD_ENABLE, out_mem_bEnable => MEM_WRITE_BYTE_ENABLE, out_mem_readEnable => MEM_READ_ENABLE, mem_writeMask => open, interrupt_request => INT_TRIGGER, interrupt_ack => INT_ACK, -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine. interrupt_done => INT_DONE, -- Interrupt service routine completed/done. break => open, debug_txd => UART2_TX, -- Debug serial output. -- MEM_A_WRITE_ENABLE => MEM_A_WRITE_ENABLE, MEM_A_ADDR => MEM_A_ADDR, MEM_A_WRITE => MEM_A_WRITE, MEM_B_WRITE_ENABLE => MEM_B_WRITE_ENABLE, MEM_B_ADDR => MEM_B_ADDR, MEM_B_WRITE => MEM_B_WRITE, MEM_A_READ => MEM_A_READ, MEM_B_READ => MEM_B_READ ); end generate; ZPUMEDIUM: if ZPU_MEDIUM = 1 generate ZPU0 : zpu_core_medium generic map ( CLK_FREQ => SYSCLK_FREQUENCY, STACK_ADDR => SOC_STACK_ADDR -- Initial stack address on CPU start. ) port map ( clk => SYSCLK, areset => not RESET_n, enable => '1', in_mem_busy => MEM_BUSY, mem_read => MEM_DATA_READ, mem_write => MEM_DATA_WRITE, out_mem_addr => MEM_ADDR, out_mem_writeEnable => MEM_WRITE_ENABLE, out_mem_hEnable => MEM_WRITE_HWORD_ENABLE, out_mem_bEnable => MEM_WRITE_BYTE_ENABLE, out_mem_readEnable => MEM_READ_ENABLE, mem_writeMask => open, interrupt_request => INT_TRIGGER, interrupt_ack => INT_ACK, -- Interrupt acknowledge, ZPU has entered Interrupt Service Routine. interrupt_done => INT_DONE, -- Interrupt service routine completed/done. break => open, debug_txd => UART2_TX -- Debug serial output. ); end generate; ZPUEVO: if ZPU_EVO = 1 generate ZPU0 : zpu_core_evo generic map ( -- Optional hardware features to be implemented. IMPL_HW_BYTE_WRITE => EVO_USE_HW_BYTE_WRITE, -- Enable use of hardware direct byte write rather than read 33bits-modify 8 bits-write 32bits. IMPL_HW_WORD_WRITE => EVO_USE_HW_WORD_WRITE, -- Enable use of hardware direct byte write rather than read 32bits-modify 16 bits-write 32bits. IMPL_OPTIMIZE_IM => IMPL_EVO_OPTIMIZE_IM, -- If the instruction cache is enabled, optimise Im instructions to gain speed. IMPL_USE_INSN_BUS => SOC_IMPL_INSN_BRAM, -- Use a seperate bus to read instruction memory, normally implemented in BRAM. IMPL_USE_WB_BUS => EVO_USE_WB_BUS, -- Use the wishbone interface in addition to direct access bus. -- Optional instructions to be implemented in hardware: IMPL_ASHIFTLEFT => IMPL_EVO_ASHIFTLEFT, -- Arithmetic Shift Left (uses same logic so normally combined with ASHIFTRIGHT and LSHIFTRIGHT). IMPL_ASHIFTRIGHT => IMPL_EVO_ASHIFTRIGHT, -- Arithmetic Shift Right. IMPL_CALL => IMPL_EVO_CALL, -- Call to direct address. IMPL_CALLPCREL => IMPL_EVO_CALLPCREL, -- Call to indirect address (add offset to program counter). IMPL_DIV => IMPL_EVO_DIV, -- 32bit signed division. IMPL_EQ => IMPL_EVO_EQ, -- Equality test. IMPL_EXTENDED_INSN => IMPL_EVO_EXTENDED_INSN, -- Extended multibyte instruction set. IMPL_FIADD32 => IMPL_EVO_FIADD32, -- Fixed point Q17.15 addition. IMPL_FIDIV32 => IMPL_EVO_FIDIV32, -- Fixed point Q17.15 division. IMPL_FIMULT32 => IMPL_EVO_FIMULT32, -- Fixed point Q17.15 multiplication. IMPL_LOADB => IMPL_EVO_LOADB, -- Load single byte from memory. IMPL_LOADH => IMPL_EVO_LOADH, -- Load half word (16bit) from memory. IMPL_LSHIFTRIGHT => IMPL_EVO_LSHIFTRIGHT, -- Logical shift right. IMPL_MOD => IMPL_EVO_MOD, -- 32bit modulo (remainder after division). IMPL_MULT => IMPL_EVO_MULT, -- 32bit signed multiplication. IMPL_NEG => IMPL_EVO_NEG, -- Negate value in TOS. IMPL_NEQ => IMPL_EVO_NEQ, -- Not equal test. IMPL_POPPCREL => IMPL_EVO_POPPCREL, -- Pop a value into the Program Counter from a location relative to the Stack Pointer. IMPL_PUSHSPADD => IMPL_EVO_PUSHSPADD, -- Add a value to the Stack pointer and push it onto the stack. IMPL_STOREB => IMPL_EVO_STOREB, -- Store/Write a single byte to memory/IO. IMPL_STOREH => IMPL_EVO_STOREH, -- Store/Write a half word (16bit) to memory/IO. IMPL_SUB => IMPL_EVO_SUB, -- 32bit signed subtract. IMPL_XOR => IMPL_EVO_XOR, -- Exclusive or of value in TOS. -- Size/Control parameters for the optional hardware. MAX_INSNRAM_SIZE => (2**(SOC_MAX_ADDR_INSN_BRAM_BIT)), -- Maximum size of the optional instruction BRAM on the INSN Bus. MAX_L1CACHE_BITS => MAX_EVO_L1CACHE_BITS, -- Maximum size in instructions of the Level 0 instruction cache governed by the number of bits, ie. 8 = 256 instruction cache. MAX_L2CACHE_BITS => MAX_EVO_L2CACHE_BITS, -- Maximum bit size in bytes of the Level 2 instruction cache governed by the number of bits, ie. 8 = 256 byte cache. MAX_STCACHE_BITS => MAX_EVO_STCACHE_BITS, -- Maximum size in 32bit words of the stack cache, governed by the number of bits, ie. 8 - 256 x 32bit cache. MAX_MXCACHE_BITS => MAX_EVO_MXCACHE_BITS, -- Maximum size of the memory transaction cache governed by the number of bits. RESET_ADDR_CPU => SOC_RESET_ADDR_CPU, -- Initial start address of the CPU. START_ADDR_MEM => SOC_START_ADDR_MEM, -- Start address of program memory. STACK_ADDR => SOC_STACK_ADDR, -- Initial stack address on CPU start. CLK_FREQ => SYSCLK_FREQUENCY -- System clock frequency. ) port map ( CLK => SYSCLK, RESET => not RESET_n, ENABLE => '1', MEM_BUSY => MEM_BUSY, MEM_DATA_IN => MEM_DATA_READ, MEM_DATA_OUT => MEM_DATA_WRITE, MEM_ADDR => MEM_ADDR, MEM_WRITE_ENABLE => MEM_WRITE_ENABLE, MEM_READ_ENABLE => MEM_READ_ENABLE, MEM_WRITE_BYTE => MEM_WRITE_BYTE_ENABLE, MEM_WRITE_HWORD => MEM_WRITE_HWORD_ENABLE, MEM_BUSRQ => '0', MEM_BUSACK => open, -- Instruction memory path. MEM_BUSY_INSN => '0', MEM_DATA_IN_INSN => MEM_DATA_READ_INSN, MEM_ADDR_INSN => MEM_ADDR_INSN, MEM_READ_ENABLE_INSN => MEM_READ_ENABLE_INSN, -- Master Wishbone Memory/IO bus interface. WB_CLK_I => WB_CLK_I, WB_RST_I => not RESET_n, WB_ACK_I => WB_ACK_I, WB_DAT_I => WB_DAT_I, WB_DAT_O => WB_DAT_O, WB_ADR_O => WB_ADR_O, WB_CYC_O => WB_CYC_O, WB_STB_O => WB_STB_O, WB_CTI_O => WB_CTI_O, WB_WE_O => WB_WE_O, WB_SEL_O => WB_SEL_O, WB_HALT_I => WB_HALT_I, WB_ERR_I => WB_ERR_I, WB_INTA_I => WB_INTA_I, -- 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, -- 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; ZPUEVOMIN: if ZPU_EVO_MINIMAL = 1 generate ZPU0 : zpu_core_evo generic map ( -- Optional hardware features to be implemented. IMPL_HW_BYTE_WRITE => EVO_USE_HW_BYTE_WRITE, -- Enable use of hardware direct byte write rather than read 33bits-modify 8 bits-write 32bits. IMPL_HW_WORD_WRITE => EVO_USE_HW_WORD_WRITE, -- Enable use of hardware direct byte write rather than read 32bits-modify 16 bits-write 32bits. IMPL_OPTIMIZE_IM => IMPL_EVOM_OPTIMIZE_IM, -- If the instruction cache is enabled, optimise Im instructions to gain speed. IMPL_USE_INSN_BUS => SOC_IMPL_INSN_BRAM, -- Use a seperate bus to read instruction memory, normally implemented in BRAM. IMPL_USE_WB_BUS => EVO_USE_WB_BUS, -- Use the wishbone interface in addition to direct access bus. -- Optional instructions to be implemented in hardware: IMPL_ASHIFTLEFT => IMPL_EVOM_ASHIFTLEFT, -- Arithmetic Shift Left (uses same logic so normally combined with ASHIFTRIGHT and LSHIFTRIGHT). IMPL_ASHIFTRIGHT => IMPL_EVOM_ASHIFTRIGHT, -- Arithmetic Shift Right. IMPL_CALL => IMPL_EVOM_CALL, -- Call to direct address. IMPL_CALLPCREL => IMPL_EVOM_CALLPCREL, -- Call to indirect address (add offset to program counter). IMPL_DIV => IMPL_EVOM_DIV, -- 32bit signed division. IMPL_EQ => IMPL_EVOM_EQ, -- Equality test. IMPL_EXTENDED_INSN => IMPL_EVOM_EXTENDED_INSN, -- Extended multibyte instruction set. IMPL_FIADD32 => IMPL_EVOM_FIADD32, -- Fixed point Q17.15 addition. IMPL_FIDIV32 => IMPL_EVOM_FIDIV32, -- Fixed point Q17.15 division. IMPL_FIMULT32 => IMPL_EVOM_FIMULT32, -- Fixed point Q17.15 multiplication. IMPL_LOADB => IMPL_EVOM_LOADB, -- Load single byte from memory. IMPL_LOADH => IMPL_EVOM_LOADH, -- Load half word (16bit) from memory. IMPL_LSHIFTRIGHT => IMPL_EVOM_LSHIFTRIGHT, -- Logical shift right. IMPL_MOD => IMPL_EVOM_MOD, -- 32bit modulo (remainder after division). IMPL_MULT => IMPL_EVOM_MULT, -- 32bit signed multiplication. IMPL_NEG => IMPL_EVOM_NEG, -- Negate value in TOS. IMPL_NEQ => IMPL_EVOM_NEQ, -- Not equal test. IMPL_POPPCREL => IMPL_EVOM_POPPCREL, -- Pop a value into the Program Counter from a location relative to the Stack Pointer. IMPL_PUSHSPADD => IMPL_EVOM_PUSHSPADD, -- Add a value to the Stack pointer and push it onto the stack. IMPL_STOREB => IMPL_EVOM_STOREB, -- Store/Write a single byte to memory/IO. IMPL_STOREH => IMPL_EVOM_STOREH, -- Store/Write a half word (16bit) to memory/IO. IMPL_SUB => IMPL_EVOM_SUB, -- 32bit signed subtract. IMPL_XOR => IMPL_EVOM_XOR, -- Exclusive or of value in TOS. -- Size/Control parameters for the optional hardware. MAX_INSNRAM_SIZE => (2**(SOC_MAX_ADDR_INSN_BRAM_BIT)), -- Maximum size of the optional instruction BRAM on the INSN Bus. MAX_L1CACHE_BITS => MAX_EVO_MIN_L1CACHE_BITS, -- Maximum size in instructions of the Level 0 instruction cache governed by the number of bits, ie. 8 = 256 instruction cache. MAX_L2CACHE_BITS => MAX_EVO_MIN_L2CACHE_BITS, -- Maximum size in bytes of the Level 2 instruction cache governed by the number of bits, ie. 8 = 256 byte cache. MAX_STCACHE_BITS => MAX_EVO_MIN_STCACHE_BITS, -- Maximum size in 32bit words of the stack cache, governed by the number of bits, ie. 8 - 256 x 32bit cache. MAX_MXCACHE_BITS => MAX_EVO_MIN_MXCACHE_BITS, -- Maximum size of the memory transaction cache governed by the number of bits. RESET_ADDR_CPU => SOC_RESET_ADDR_CPU, -- Initial start address of the CPU. START_ADDR_MEM => SOC_START_ADDR_MEM, -- Start address of program memory. STACK_ADDR => SOC_STACK_ADDR, -- Initial stack address on CPU start. CLK_FREQ => SYSCLK_FREQUENCY -- System clock frequency. ) port map ( CLK => SYSCLK, RESET => not RESET_n, ENABLE => '1', MEM_BUSY => MEM_BUSY, MEM_DATA_IN => MEM_DATA_READ, MEM_DATA_OUT => MEM_DATA_WRITE, MEM_ADDR => MEM_ADDR, MEM_WRITE_ENABLE => MEM_WRITE_ENABLE, MEM_READ_ENABLE => MEM_READ_ENABLE, MEM_WRITE_BYTE => MEM_WRITE_BYTE_ENABLE, MEM_WRITE_HWORD => MEM_WRITE_HWORD_ENABLE, MEM_BUSRQ => '0', MEM_BUSACK => open, -- Instruction memory path. MEM_BUSY_INSN => '0', MEM_DATA_IN_INSN => MEM_DATA_READ_INSN, MEM_ADDR_INSN => MEM_ADDR_INSN, MEM_READ_ENABLE_INSN => MEM_READ_ENABLE_INSN, -- Master Wishbone Memory/IO bus interface. WB_CLK_I => WB_CLK_I, WB_RST_I => not RESET_n, WB_ACK_I => WB_ACK_I, WB_DAT_I => WB_DAT_I, WB_DAT_O => WB_DAT_O, WB_ADR_O => WB_ADR_O, WB_CYC_O => WB_CYC_O, WB_STB_O => WB_STB_O, WB_CTI_O => WB_CTI_O, WB_WE_O => WB_WE_O, WB_SEL_O => WB_SEL_O, WB_HALT_I => WB_HALT_I, WB_ERR_I => WB_ERR_I, WB_INTA_I => WB_INTA_I, -- 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, -- 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; -- ROM ZPUROMSMALL : if (ZPU_SMALL = 1 or ZPU_FLEX = 1) and SOC_IMPL_BRAM = true generate ZPUROM : entity work.BootROM port map ( clk => SYSCLK, memAWriteEnable => MEM_A_WRITE_ENABLE, memAAddr => MEM_A_ADDR(ADDR_32BIT_BRAM_RANGE), memAWrite => MEM_A_WRITE, memBWriteEnable => MEM_B_WRITE_ENABLE, memBAddr => MEM_B_ADDR(ADDR_32BIT_BRAM_RANGE), memBWrite => MEM_B_WRITE, memARead => MEM_A_READ, memBRead => MEM_B_READ ); end generate; -- This block should provide byte addressable dual port BRAM for the Flex but for some reason Quartus quarks when compiling when the B port is used for writes. Not sure why -- but needs revisiting as it will gain some performance improvements for the flex core. --ZPUROMFLEX : if ZPU_FLEX = 1 and SOC_IMPL_BRAM = true generate -- ZPUROM : entity work.DualPortBootBRAM -- generic map ( -- addrbits => SOC_MAX_ADDR_BRAM_BIT -- ) -- port map ( -- clk => SYSCLK, -- memAAddr => MEM_A_ADDR(17 downto 2), -- memAWriteEnable => MEM_A_WRITE_ENABLE, -- memAWriteByte => MEM_WRITE_BYTE_ENABLE, -- memAWriteHalfWord => MEM_WRITE_HWORD_ENABLE, -- memAWrite => MEM_A_WRITE, -- memARead => MEM_A_READ, -- memBAddr => MEM_B_ADDR(ADDR_32BIT_BRAM_RANGE), -- memBWrite => MEM_B_WRITE, -- memBWriteEnable => MEM_B_WRITE_ENABLE, -- memBRead => MEM_B_READ -- ); --end generate; ZPUROMMEDIUM : if ZPU_MEDIUM = 1 and SOC_IMPL_BRAM = true generate ZPUROM : entity work.BootROM port map ( clk => SYSCLK, memAWriteEnable => BRAM_WREN, memAAddr => MEM_ADDR(ADDR_32BIT_BRAM_RANGE), memAWrite => MEM_DATA_WRITE, memBWriteEnable => '0', memBAddr => MEM_ADDR(ADDR_32BIT_BRAM_RANGE), memBWrite => (others => '0'), memARead => open, memBRead => BRAM_DATA_READ ); 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 ZPUBRAM : entity work.DualPort3264BootBRAM generic map ( addrbits => SOC_MAX_ADDR_BRAM_BIT ) port map ( clk => SYSCLK, memAAddr => MEM_ADDR(ADDR_BIT_BRAM_RANGE), memAWriteEnable => BRAM_WREN, memAWriteByte => MEM_WRITE_BYTE_ENABLE, memAWriteHalfWord => MEM_WRITE_HWORD_ENABLE, memAWrite => MEM_DATA_WRITE, memARead => BRAM_DATA_READ, memBAddr => MEM_ADDR_INSN(ADDR_64BIT_BRAM_RANGE), memBWrite => (others => '0'), memBWriteEnable => '0', memBRead => MEM_DATA_READ_INSN ); end generate; -- Evo system BRAM, single port as no seperate instruction bus configured. ZPUBRAMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_INSN_BRAM = false and SOC_IMPL_BRAM = true generate ZPUBRAM : entity work.SinglePortBootBRAM generic map ( addrbits => SOC_MAX_ADDR_BRAM_BIT ) port map ( clk => SYSCLK, memAAddr => MEM_ADDR(ADDR_BIT_BRAM_RANGE), memAWriteEnable => BRAM_WREN, memAWriteByte => MEM_WRITE_BYTE_ENABLE, memAWriteHalfWord => MEM_WRITE_HWORD_ENABLE, memAWrite => MEM_DATA_WRITE, memARead => BRAM_DATA_READ ); end generate; -- Evo RAM, a seperate block of RAM created in BRAM in addition to the main system BRAM, generally used for applications and termed RAM in this module. ZPURAMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_RAM = true generate ZPURAM : entity work.SinglePortBRAM generic map ( addrbits => SOC_MAX_ADDR_RAM_BIT ) port map ( clk => SYSCLK, memAAddr => MEM_ADDR(ADDR_BIT_RAM_RANGE), memAWriteEnable => RAM_WREN, memAWriteByte => MEM_WRITE_BYTE_ENABLE, memAWriteHalfWord => MEM_WRITE_HWORD_ENABLE, memAWrite => MEM_DATA_WRITE, memARead => RAM_DATA_READ ); -- RAM Range SOC_ADDR_RAM_START) -> SOC_ADDR_RAM_END RAM_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_RAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR < std_logic_vector(to_unsigned(SOC_ADDR_RAM_END, MEM_ADDR'LENGTH))) else '0'; -- Enable write to RAM when selected and CPU in write state. RAM_WREN <= '1' when RAM_SELECT = '1' and MEM_WRITE_ENABLE = '1' else '0'; end generate; -- SDRAM over System bus. ZPUSDRAMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and SOC_IMPL_SDRAM = true and (BOARD_QMV = true or BOARD_CYC1000 = true) generate ZPUSDRAM : entity work.SDRAM generic map ( SDRAM_ROWS => SOC_SDRAM_ROWS, -- Number of Rows in the SDRAM. SDRAM_COLUMNS => SOC_SDRAM_COLUMNS, -- Number of Columns in an SDRAM page (ie. 1 row). SDRAM_BANKS => SOC_SDRAM_BANKS, -- Number of banks in the SDRAM. SDRAM_DATAWIDTH => SOC_SDRAM_DATAWIDTH, -- Data width of SDRAM chip (ie. 16, 32). SDRAM_CLK_FREQ => SOC_SDRAM_CLK_FREQ, -- Frequency of SDRAM clock in Hertz. SDRAM_tRCD => SOC_SDRAM_tRCD, -- tRCD - RAS to CAS minimum period (in ns), ie. 20ns -> 2 cycles@100MHz SDRAM_tRP => SOC_SDRAM_tRP, -- tRP - Precharge delay, min time for a precharge command to complete (in ns), ie. 15ns -> 2 cycles@100MHz SDRAM_tRFC => SOC_SDRAM_tRFC, -- tRFC - Auto-refresh minimum time to complete (in ns), ie. 66ns SDRAM_tREF => SOC_SDRAM_tREF -- tREF - period of time a complete refresh of all rows is made within (in ms). ) port map ( -- SDRAM Interface SDRAM_CLK => MEMCLK, -- sdram clock running at an offset from system clock. SDRAM_RST => not RESET_n, -- reset the sdram controller. SDRAM_CKE => SDRAM_CKE, -- clock enable. SDRAM_DQ => SDRAM_DQ, -- 16 bit bidirectional data bus SDRAM_ADDR => SDRAM_ADDR, -- 12 bit multiplexed address bus SDRAM_DQM => SDRAM_DQM, -- two byte masks SDRAM_BA => SDRAM_BA, -- two banks SDRAM_CS_n => SDRAM_CS_n, -- a single chip select SDRAM_WE_n => SDRAM_WE_n, -- write enable SDRAM_RAS_n => SDRAM_RAS_n, -- row address select SDRAM_CAS_n => SDRAM_CAS_n, -- columns address select SDRAM_READY => SDRAM_READY, -- sd ready. -- CPU Interface CLK => SYSCLK, -- System master clock RESET => not RESET_n, -- high active sync reset ADDR => MEM_ADDR(ADDR_BIT_SDRAM_RANGE), DATA_IN => MEM_DATA_WRITE, -- write data DATA_OUT => SDRAM_DATA_READ, -- read data WRITE_BYTE => MEM_WRITE_BYTE_ENABLE, -- Write a single byte. WRITE_HWORD => MEM_WRITE_HWORD_ENABLE, -- Write a 16 bit word. CS => SDRAM_SELECT, -- Chip Select. WREN => SDRAM_WREN, -- Write enable. RDEN => SDRAM_RDEN, -- Read enable. BUSY => SDRAM_MEM_BUSY ); -- SDRAM clock based on system clock. SDRAM_CLK <= MEMCLK; -- RAM Range SOC_ADDR_SDRAM_START) -> SOC_ADDR_SDRAM_END SDRAM_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_SDRAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR < std_logic_vector(to_unsigned(SOC_ADDR_SDRAM_END, MEM_ADDR'LENGTH))) --SDRAM_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_RAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR < std_logic_vector(to_unsigned(SOC_ADDR_RAM_END, MEM_ADDR'LENGTH))) else '0'; -- Enable write to RAM when selected and CPU in write state. SDRAM_WREN <= MEM_WRITE_ENABLE when SDRAM_SELECT = '1' else '0'; SDRAM_RDEN <= MEM_READ_ENABLE when SDRAM_SELECT = '1' else '0'; end generate; -- Force the CPU to wait when slower memory/IO is accessed and it cant deliver an immediate result. MEM_BUSY <= '1' when (UART0_CS = '1' or UART1_CS = '1' or TIMER0_CS = '1') and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' else '1' when SOC_IMPL_SDRAM = true and (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and SDRAM_MEM_BUSY = '1' and (BOARD_QMV = true or BOARD_CYC1000 = true) else -- '1' when BRAM_SELECT = '1' and (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (MEM_READ_ENABLE = '1') -- else -- '1' when IO_SELECT = '1' and (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (MEM_READ_ENABLE = '1') -- else '1' when SOC_IMPL_SD = true and SD_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' else '1' when SOC_IMPL_SPI = true and SPI_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' and IO_WAIT_SPI = '1' else '1' when SOC_IMPL_PS2 = true and PS2_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' and IO_WAIT_PS2 = '1' else '1' when SOC_IMPL_INTRCTL = true and INTR0_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' and IO_WAIT_INTR = '1' else '1' when SOC_IMPL_TIMER1 = true and TIMER1_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' and IO_WAIT_TIMER1 = '1' else '1' when SOC_IMPL_IOCTL = true and IOCTL_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' and IO_WAIT_IOCTL = '1' and (BOARD_CYC1000 = true or BOARD_DE10 = true) else '1' when SOC_IMPL_SOCCFG = true and SOCCFG_CS = '1' and MEM_READ_ENABLE_LAST = '0' and MEM_READ_ENABLE = '1' else '0'; -- Select CPU input source, memory or IO. MEM_DATA_READ <= BRAM_DATA_READ when BRAM_SELECT = '1' else RAM_DATA_READ when SOC_IMPL_RAM = true and RAM_SELECT = '1' else SDRAM_DATA_READ when SOC_IMPL_SDRAM = true and SDRAM_SELECT = '1' and (BOARD_QMV = true or BOARD_CYC1000 = true) else IO_DATA_READ_SD when SOC_IMPL_SD = true and SD_CS = '1' else IO_DATA_READ_SPI when SOC_IMPL_SPI = true and SPI0_CS = '1' else IO_DATA_READ_PS2 when SOC_IMPL_PS2 = true and PS2_CS = '1' else IO_DATA_READ_INTRCTL when SOC_IMPL_INTRCTL = true and INTR0_CS = '1' else IO_DATA_READ_SOCCFG when SOC_IMPL_SOCCFG = true and SOCCFG_CS = '1' else IO_DATA_READ_IOCTL when SOC_IMPL_IOCTL = true and IOCTL_CS = '1' and (BOARD_CYC1000 = true or BOARD_DE10 = true) else IO_DATA_READ when IO_SELECT = '1' else (others => '1'); -- If the wishbone interface is implemented, generate the control and decode logic. WISHBONE_CTRL: if SOC_IMPL_WB = true generate WB_DAT_I <= WB_DATA_READ_SDRAM when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_WB_SDRAM = true and WB_SDRAM_STB = '1' else X"000000" & WB_DATA_READ_I2C(BYTE_RANGE) when SOC_IMPL_WB_I2C = true and WB_I2C_CS = '1' else (others => '0'); -- Acknowledge is a chain of all enabled device acknowledges as only the addressed device in any given occasion should generate an ACK. WB_ACK_I <= WB_SDRAM_ACK when SOC_IMPL_WB_SDRAM = true and WB_SDRAM_STB = '1' else WB_I2C_ACK when SOC_IMPL_WB_I2C = true and WB_I2C_CS = '1' -- access to an unimplemented area of memory, just ACK as there is nothing to handle the request. else '1'; -- Halt/Wait signal is a chain of all enabled devices requiring additional bus transaction time. WB_HALT_I <= WB_I2C_HALT when SOC_IMPL_WB_I2C = true and WB_I2C_HALT = '1' else '0'; -- Error signal is a chain of all enabled device error condition signals. WB_ERR_I <= WB_I2C_ERR when SOC_IMPL_WB_I2C = true and WB_I2C_ERR = '1' else '0'; -- Interrupt signals are chained with the actual interrupt being stored in the main interrupt controller. WB_INTA_I <= WB_I2C_IRQ when SOC_IMPL_WB_I2C = true and WB_I2C_IRQ = '1' else '0'; -- Like direct I/O, place peripherals in upper range of wishbone address space. WB_IO_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and WB_STB_O = '1' and (WB_ADR_O >= std_logic_vector(to_unsigned(SOC_WB_IO_START, WB_ADR_O'LENGTH)) and WB_ADR_O < std_logic_vector(to_unsigned(SOC_WB_IO_END, WB_ADR_O'LENGTH))) else '0'; WB_IO_SOC_SELECT <= WB_IO_SELECT when WB_ADR_O(19 downto 12) = X"00" else '0'; WB_I2C_CS <= '1' when WB_IO_SOC_SELECT = '1' and WB_ADR_O(11 downto 8) = "0000" -- I2C Range 0xF000xx else '0'; WB_CLK_I <= SYSCLK; else generate WB_DAT_I <= (others => '0'); WB_ACK_I <= '0'; WB_HALT_I <= '0'; WB_ERR_I <= '0'; end generate; -- Enable write to System BRAM when selected and CPU in write state. BRAM_WREN <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and MEM_WRITE_ENABLE = '1' and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR <= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_END, MEM_ADDR'LENGTH))) else '1' when ZPU_MEDIUM = 1 and MEM_WRITE_ENABLE = '1' and MEM_ADDR(ioBit) = '0' and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR <= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_END, MEM_ADDR'LENGTH))) else '0'; -- Were not interested in the mouse, so pass through connection. PS2M_CLK_OUT <= PS2M_CLK_IN; PS2M_DAT_OUT <= PS2M_DAT_IN; -- Fixed peripheral Decoding. -- BRAM Range 0x00000000 - (2^SOC_MAX_ADDR_INSN_BRAM_BIT)-1 BRAM_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR < std_logic_vector(to_unsigned(SOC_ADDR_BRAM_END, MEM_ADDR'LENGTH))) else '1' when ZPU_MEDIUM = 1 and (MEM_ADDR >= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_START, MEM_ADDR'LENGTH)) and MEM_ADDR < std_logic_vector(to_unsigned(SOC_ADDR_BRAM_END, MEM_ADDR'LENGTH))) else '1' when (ZPU_FLEX = 1 or ZPU_SMALL = 1) and MEM_ADDR(ioBit) = '0' else '0'; -- IO Range for EVO CPU IO_SELECT <= '1' when (ZPU_SMALL = 1 or ZPU_MEDIUM = 1 or ZPU_FLEX = 1) and MEM_ADDR(ioBit) = '1' -- IO Range for Small, Medium and Flex CPU else -- '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and MEM_ADDR(IO_DECODE_RANGE) = std_logic_vector(to_unsigned(255, maxAddrBit - maxIOBit)) and MEM_ADDR(maxIOBit -1 downto 12) = std_logic_vector(to_unsigned(0, maxIOBit-12)) '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and ((SOC_IMPL_WB = true and MEM_ADDR(WB_SELECT_BIT) = '0') or SOC_IMPL_WB = false) and MEM_ADDR(IO_DECODE_RANGE) = std_logic_vector(to_unsigned(255, maxAddrBit-WB_ACTIVE - maxIOBit)) and MEM_ADDR(maxIOBit -1 downto 12) = std_logic_vector(to_unsigned(0, maxIOBit-12)) else '0'; IO_TIMER_SELECT <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 8) = X"C" -- Timer Range 0xFFFFCxx else '0'; UART0_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "10100000" -- Uart Range 0xFFFFAxx, 0xA00-C0F else '0'; UART1_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "10100001" -- Uart Range 0xFFFFAxx, 0xA10-A1F else '0'; TIMER0_CS <= '1' when IO_TIMER_SELECT = '1' and MEM_ADDR(7 downto 6) = "00" -- 0xC00-C3F Millisecond timer. else '0'; SD_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 7) = "10010" -- 0x900-90F 0xFFFF9xx, 0x900 - 0x90f First SD Card address range else '0'; -- Mux the UART debug channel outputs. DBG1 is from the software controlled UART, DBG2 from the cpu channel. DEBUGUART: if DEBUG_CPU = true generate UART_TX_1 <= UART2_TX; else generate UART_TX_1 <= UART1_TX; end generate; ------------------------------------------------------------------------------------ -- Direct Memory I/O devices ------------------------------------------------------------------------------------ TIMER : if SOC_IMPL_TIMER1 = true generate -- TIMER TIMER1 : entity work.timer_controller generic map( prescale => 1, -- Prescale incoming clock timers => SOC_TIMER1_COUNTERS ) port map ( clk => SYSCLK, reset => RESET_n, reg_addr_in => MEM_ADDR(7 downto 0), reg_data_in => MEM_DATA_WRITE, reg_rw => '0', -- we never read from the timers reg_req => TIMER_REG_REQ, ticks(0) => TIMER1_TICK -- Tick signal is used to trigger an interrupt ); process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then TIMER_REG_REQ <= '0'; IO_WAIT_TIMER1 <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then IO_WAIT_TIMER1 <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and TIMER1_CS = '1' then -- Write to Timer. TIMER_REG_REQ <= '1'; -- IO Read? elsif MEM_READ_ENABLE = '1' and TIMER1_CS = '1' then end if; end if; -- rising-edge(SYSCLK) end process; TIMER1_CS <= '1' when IO_TIMER_SELECT = '1' and MEM_ADDR(7 downto 6) = "01" -- 0xC40-C7F else '0'; else generate TIMER_REG_REQ <= '0'; IO_WAIT_TIMER1 <= '0'; end generate; -- PS2 devices PS2 : if SOC_IMPL_PS2 = true generate PS2KEYBOARD : entity work.io_ps2_com generic map ( clockFilter => 15, ticksPerUsec => SYSCLK_FREQUENCY/1000000 ) port map ( clk => SYSCLK, reset => not RESET_n, ps2_clk_in => PS2K_CLK_IN, ps2_dat_in => PS2K_DAT_IN, ps2_clk_out => PS2K_CLK_OUT, ps2_dat_out => PS2K_DAT_OUT, inIdle => open, sendTrigger => KBD_SEND_TRIGGER, sendByte => KBD_SEND_BYTE, sendBusy => KBD_SEND_BUSY, sendDone => KBD_SEND_DONE, recvTrigger => KBD_RECV, recvByte => KBD_RECV_BYTE ); process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then KBD_SEND_TRIGGER <= '0'; KBD_RECV_REG <= '0'; IO_WAIT_PS2 <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then KBD_SEND_TRIGGER <= '0'; IO_WAIT_PS2 <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and PS2_CS = '1' then -- Write to PS2 Controller. KBD_SEND_BYTE <= MEM_DATA_WRITE(7 downto 0); KBD_SEND_TRIGGER <='1'; -- IO Read? elsif MEM_READ_ENABLE = '1' and PS2_CS = '1' then -- Read from PS2. IO_DATA_READ_PS2 <=(others =>'0'); IO_DATA_READ_PS2(11 downto 0) <= KBD_RECV_REG & not KBD_SEND_BUSY & KBD_RECV_BYTE(10 downto 1); KBD_RECV_REG <='0'; end if; -- PS2 interrupt PS2_INT <= KBD_RECV or KBD_SEND_DONE; if KBD_RECV='1' then KBD_RECV_REG <= '1'; -- remains high until cleared by a read end if; end if; -- rising-edge(SYSCLK) end process; PS2_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "11010000" -- PS2 Range 0xFFFFFExx, 0xE00-E0F else '0'; else generate PS2_INT <= '0'; PS2_CS <= '0'; KBD_SEND_TRIGGER <= '0'; KBD_RECV_REG <= '0'; IO_WAIT_PS2 <= '0'; end generate; -- SPI host SPI : if SOC_IMPL_SPI = true generate SPI0 : entity work.spi_interface port map( sysclk => SYSCLK, reset => RESET_n, -- Host interface SPICLK_IN => SPICLK_IN, HOST_TO_SPI => HOST_TO_SPI, SPI_TO_HOST => SPI_TO_HOST, trigger => SPI_TRIGGER, busy => SPI_BUSY, -- Hardware interface miso => SPI_MISO, mosi => SPI_MOSI, spiclk_out => SPI_CLK ); -- SPI Timer process(SYSCLK) begin if rising_edge(SYSCLK) then SPICLK_IN <= '0'; SPI_TICK <= SPI_TICK+1; if (SPI_FAST='1' and SPI_TICK(5)='1') or SPI_TICK(8)='1' then SPICLK_IN <= '1'; -- Momentary pulse for SPI host. SPI_TICK <= '0' & X"00"; end if; end if; end process; process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then SPI_CS <= '1'; SPI_ACTIVE <= '0'; IO_WAIT_SPI <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then SPI_TRIGGER <= '0'; IO_WAIT_SPI <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and SPI0_CS = '1' then -- Write to the SPI. case MEM_ADDR(3 downto 2) is when "00" => -- SPI CS SPI_CS <= not MEM_DATA_WRITE(0); SPI_FAST <= MEM_DATA_WRITE(8); when "01" => -- SPI Data SPI_WIDE <='0'; SPI_TRIGGER <= '1'; HOST_TO_SPI <= MEM_DATA_WRITE(7 downto 0); SPI_ACTIVE <= '1'; IO_WAIT_SPI <= '1'; when "10" => -- SPI Pump (32-bit read) SPI_WIDE <= '1'; SPI_TRIGGER <= '1'; HOST_TO_SPI <= MEM_DATA_WRITE(7 downto 0); SPI_ACTIVE <= '1'; IO_WAIT_SPI <= '1'; when others => end case; -- IO Read? elsif MEM_READ_ENABLE = '1' and SPI0_CS = '1' then -- Read from SPI. case MEM_ADDR(3 downto 2) is when "00" => -- SPI CS IO_DATA_READ_SPI <= (others =>'X'); IO_DATA_READ_SPI(15) <= SPI_BUSY; when "01" => -- SPI Data SPI_ACTIVE <= '1'; IO_WAIT_SPI <= '1'; when "10" => -- SPI Pump (32-bit read) SPI_WIDE <= '1'; SPI_TRIGGER <= '1'; SPI_ACTIVE <= '1'; HOST_TO_SPI <= X"FF"; IO_WAIT_SPI <= '1'; when others => end case; end if; -- SPI cycles if SPI_ACTIVE='1' then IO_WAIT_SPI <= SPI_BUSY; if SPI_BUSY = '0' then IO_DATA_READ_SPI <= SPI_TO_HOST; SPI_ACTIVE <= '0'; end if; end if; end if; -- rising-edge(SYSCLK) end process; SPI0_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "11010000" -- SPI Range 0xFFFFFDxx, 0xD00-D0F else '0'; else generate SPI_CS <= '1'; SPI_ACTIVE <= '0'; IO_WAIT_SPI <= '0'; end generate; -- SD Card interface. Upto 4 SD Cards can be configured, add an entity for each and set the generics to the values required. -- The signals are in the form of an array, so device 0 uses signals in array element 0. SDCARD0: if SOC_IMPL_SD = true and SOC_SD_DEVICES >= 1 generate SDCARDS: for I in 0 to SOC_SD_DEVICES-1 generate SDCARD : entity work.SDCard generic map ( FREQ_G => (Real(SYSCLK_FREQUENCY / 1000000)), -- Master clock frequency (MHz). INIT_SPI_FREQ_G => 0.4, -- Slow SPI clock freq. during initialization (MHz). SPI_FREQ_G => 25.0, -- Operational SPI freq. to the SD card (MHz). BLOCK_SIZE_G => 512 -- Number of bytes in an SD card block or sector. ) port map ( -- Host-side interface signals. clk_i => SYSCLK, -- Master clock. reset_i => SD_RESET(I), -- active-high, synchronous reset. cardtype => SD_CARD_TYPE(I), -- 0 = SD, 1 = SDHC. rd_i => SD_RD(I), -- active-high read block request. wr_i => SD_WR(I), -- active-high write block request. continue_i => SD_CONTINUE(I), -- If true, inc address and continue R/W. addr_i => SD_ADDR(I), -- Block address. data_i => SD_DATA_WRITE(7 downto 0), -- Data to write to block. data_o => SD_DATA_READ(I)(7 downto 0), -- Data read from block. busy_o => SD_BUSY(I), -- High when controller is busy performing some operation. hndShk_i => SD_HNDSHK_IN(I), -- High when host has data to give or has taken data. hndShk_o => SD_HNDSHK_OUT(I), -- High when controller has taken data or has data to give. error_o => SD_ERROR(I), -- Card error occurred (1). -- I/O signals to the external SD card. cs_bo => SDCARD_CS(I), -- Active-low chip-select. sclk_o => SDCARD_CLK(I), -- Serial clock to SD card. mosi_o => SDCARD_MOSI(I), -- Serial data output to SD card. miso_i => SDCARD_MISO(I) -- Serial data input from SD card. ); end generate; end generate; -- SDCARDCTL: if SOC_IMPL_SD = true and SOC_SD_DEVICES >= 1 generate process(SYSCLK, RESET_n, MEM_ADDR) variable tChannel : integer range 0 to SOC_SD_DEVICES-1; begin ------------------------ -- HIGH LEVEL -- ------------------------ -- Channel being accessed is in addr bits 5:4. tChannel := to_integer(unsigned(MEM_ADDR(6 downto 4))); ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then SD_ADDR <= (others => (others => DontCareValue)); SD_RD <= (others => '0'); SD_WR <= (others => '0'); SD_RESET <= (others => '0'); SD_CARD_TYPE <= (others => '0'); SD_CONTINUE <= (others => '0'); SD_HNDSHK_IN <= (others => '0'); SD_OVERRUN <= '0'; SD_DATA_REQ <= '0'; SD_DATA_VALID <= '0'; SD_RESET_TIMER <= 0; SD_STATE <= SD_STATE_RESET; IO_WAIT_SD <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then -- Reset wait state, only 1 cycle long under normal circumstances. IO_WAIT_SD <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and SD_CS = '1' then -- Write to the SPI. case MEM_ADDR(3 downto 2) is when "00" => -- Store address for next block operation. SD_ADDR(tChannel) <= MEM_DATA_WRITE; -- Write data latch, the host writes data to be written into this register when -- the status register SD_DATA_REQ is set. when "01" => SD_DATA_WRITE <= MEM_DATA_WRITE(7 downto 0); SD_DATA_REQ <= '0'; -- Command register, initiate transactions by setting the control bits. when "11" => -- Command if MEM_DATA_WRITE(0) = '1' then SD_STATE <= SD_STATE_RESET; elsif MEM_DATA_WRITE(1) = '1' then SD_STATE <= SD_STATE_WRITE; elsif MEM_DATA_WRITE(2) = '1' then SD_STATE <= SD_STATE_READ; elsif MEM_DATA_WRITE(3) = '1' then SD_CARD_TYPE(tChannel) <= MEM_DATA_WRITE(7); end if; SD_CHANNEL <= tChannel; when others => end case; -- IO Read? elsif MEM_READ_ENABLE = '1' and SD_CS = '1' then -- Read from SPI. IO_DATA_READ_SD <= (others => '0'); case MEM_ADDR(3 downto 2) is -- Read back stored address. when "00" => IO_DATA_READ_SD <= SD_ADDR(tChannel); IO_WAIT_SD <= '0'; -- Read Data, only valid if the SD_DATA_VALID bit is set. when "01" => IO_WAIT_SD <= '0'; IO_DATA_READ_SD(31 downto 16) <= SD_ERROR(tChannel); IO_DATA_READ_SD(7 downto 0) <= SD_DATA_READ(tChannel); SD_DATA_VALID <= '0'; -- Card status when "11" => IO_DATA_READ_SD(0) <= SD_CONTINUE(tChannel); IO_DATA_READ_SD(1) <= SD_BUSY(tChannel); IO_DATA_READ_SD(2) <= SD_HNDSHK_OUT(tChannel); IO_DATA_READ_SD(3) <= SD_HNDSHK_IN(tChannel); IO_DATA_READ_SD(4) <= SD_DATA_REQ; -- 1 when data needed for transmission. IO_DATA_READ_SD(5) <= SD_DATA_VALID; -- 1 when data available. IO_DATA_READ_SD(6) <= SD_OVERRUN; IO_DATA_READ_SD(12 downto 8) <= std_logic_vector(to_unsigned(SDStateType'POS(SD_STATE), 5)); IO_DATA_READ_SD(13) <= SD_RD(tChannel); IO_DATA_READ_SD(14) <= SD_WR(tChannel); IO_DATA_READ_SD(15) <= SD_RESET(tChannel); IO_DATA_READ_SD(31 downto 16) <= SD_ERROR(tChannel); IO_WAIT_SD <= '0'; SD_OVERRUN <= '0'; when others => end case; end if; -- State machine to process requests. case SD_STATE is when SD_STATE_IDLE => SD_RESET <= (others => '0'); SD_WR <= (others => '0'); SD_RD <= (others => '0'); ----------------------------------------- -- RESET SD card ----------------------------------------- -- To reset the card we apply a 100ns reset pulse, the card will then go through the reset procedure, asserting -- BUSY until it is ready when BUSY will be deasserted. when SD_STATE_RESET => SD_RESET_TIMER <= SYSCLK_FREQUENCY/10000000; SD_RESET(SD_CHANNEL) <= '1'; SD_STATE <= SD_STATE_RESET_1; when SD_STATE_RESET_1 => if SD_RESET_TIMER = 0 then SD_RESET(SD_CHANNEL) <= '0'; SD_STATE <= SD_STATE_IDLE; else SD_RESET_TIMER <= SD_RESET_TIMER - 1; end if; ----------------------------------------- -- WRITE a sector ----------------------------------------- -- Address of byte (SD)/block (SDHC) already applied to address input. Set SD_WR high and wait -- wait until SD_BUSY goes high. when SD_STATE_WRITE => SD_WR(SD_CHANNEL) <= '1'; SD_DATA_REQ <= '0'; if SD_BUSY(SD_CHANNEL) = '1' then SD_WR(SD_CHANNEL) <= '0'; SD_STATE <= SD_STATE_WRITE_1; end if; -- We now enter a loop, we wait for a byte to be written into the data register, then wait for the controller -- to assert HNDSHK_OUT, we raise the handshake line HNDSHK_IN and wait for the deassertion of HNDSHK_OUT to indicate completion. -- If SD_BUSY is reset then it indicates completion, either due to an error or because the entire sector was written. when SD_STATE_WRITE_1 => -- When DATA Request is clear and the controller starts a handshake, request from the host a byte. if SD_DATA_REQ = '0' and SD_HNDSHK_OUT(SD_CHANNEL) = '1' then SD_DATA_REQ <= '1'; SD_STATE <= SD_STATE_WRITE_2; -- If Busy goes inactive then we have completed, either due to an error or completion of the write. elsif SD_BUSY(SD_CHANNEL) = '0' then SD_STATE <= SD_STATE_IDLE; end if; when SD_STATE_WRITE_2 => -- When the data byte is loaded by the host, we raise our handshake line to show data available. if SD_DATA_REQ = '0' and SD_HNDSHK_OUT(SD_CHANNEL) = '1' then SD_HNDSHK_IN(SD_CHANNEL) <= '1'; -- When the controller acknowledges, lower the handshake line to complete the transaction. elsif SD_HNDSHK_OUT(SD_CHANNEL) = '0' then SD_HNDSHK_IN(SD_CHANNEL) <= '0'; SD_STATE <= SD_STATE_WRITE_1; elsif SD_BUSY(SD_CHANNEL) = '0' then SD_STATE <= SD_STATE_IDLE; end if; ----------------------------------------- -- READ a sector ----------------------------------------- -- For a read, we raise the SD_RD line and wait for SD_BUSY to go high. Once SD_BUSY is high, SD_RD is deasserted and we -- now wait for data. when SD_STATE_READ => SD_RD(SD_CHANNEL) <= '1'; SD_DATA_VALID <= '0'; if SD_BUSY(SD_CHANNEL) = '1' then SD_RD(SD_CHANNEL) <= '0'; SD_STATE <= SD_STATE_READ_1; end if; -- If SD_BUSY is ever deasserted, we are either at the end of a read or an error occurred, in either case exit to IDLE. -- We wait for the HNDSHK_OUT to be asserted, read the data, and then move to the next state. In between, if the timeout -- timer expires because the controller hasnt sent data, abort as it may have locked up. when SD_STATE_READ_1 => if SD_HNDSHK_OUT(SD_CHANNEL) = '1' then SD_DATA_VALID <= '1'; SD_HNDSHK_IN(SD_CHANNEL) <= '1'; SD_STATE <= SD_STATE_READ_2; elsif SD_BUSY(SD_CHANNEL) = '0' then SD_STATE <= SD_STATE_IDLE; elsif SD_DATA_VALID = '1' and SD_OVERRUN = '0' then SD_OVERRUN <= '1'; end if; -- Wait until the host reads the data, then assert HNDSHK_IN, the controller acknowledges by deasserting HNDSHK_OUT and at this -- point the byte read cycle is complete so we deassert HNDSHK_IN. If the timeut expires during this operation or SD_BUSY is -- deasserted, exit to IDLE due to error. when SD_STATE_READ_2 => if SD_HNDSHK_OUT(SD_CHANNEL) = '0' and SD_DATA_VALID = '0' then SD_HNDSHK_IN(SD_CHANNEL) <= '0'; SD_STATE <= SD_STATE_READ_1; elsif SD_BUSY(SD_CHANNEL) = '0' then SD_STATE <= SD_STATE_IDLE; end if; when others => end case; end if; end process; else generate SD_ADDR <= (others => (others => DontCareValue)); SD_RD <= (others => '0'); SD_WR <= (others => '0'); SD_RESET <= (others => '0'); SD_CARD_TYPE <= (others => '0'); SD_CONTINUE <= (others => '0'); SD_HNDSHK_IN <= (others => '0'); SD_OVERRUN <= '0'; SD_DATA_REQ <= '0'; SD_DATA_VALID <= '0'; SD_RESET_TIMER <= 0; SD_STATE <= SD_STATE_RESET; IO_WAIT_SD <= '0'; end generate; -- Interrupt controller INTRCTL: if SOC_IMPL_INTRCTL = true generate INTCONTROLLER : entity work.interrupt_controller generic map ( max_int => SOC_INTR_MAX ) port map ( clk => SYSCLK, reset_n => RESET_n, trigger => INT_TRIGGERS, enable_mask => INT_ENABLE, ack => INT_DONE, int => INT_REQ, status => INT_STATUS ); process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then INT_ENABLE <= (others => '0'); IO_WAIT_INTR <= '0'; IO_DATA_READ_INTRCTL <= (others => 'X'); ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then IO_WAIT_INTR <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and INTR0_CS = '1' then -- Write to interrupt controller sets the enable mask bits. case MEM_ADDR(2) is when '0' => when '1' => INT_ENABLE <= MEM_DATA_WRITE(SOC_INTR_MAX downto 0); end case; -- IO Read? elsif MEM_READ_ENABLE = '1' and INTR0_CS = '1' then -- Read interrupt status, 32 bits showing which interrupts have been triggered. IO_DATA_READ_INTRCTL <= (others => 'X'); if MEM_ADDR(2) = '0' then IO_DATA_READ_INTRCTL(SOC_INTR_MAX downto 0) <= INT_STATUS; else Io_DATA_READ_INTRCTL(SOC_INTR_MAX downto 0) <= INT_ENABLE; end if; end if; end if; -- rising-edge(SYSCLK) end process; INT_TRIGGERS <= ( 0 => '0', 1 => MICROSEC_DOWN_INTR, 2 => MILLISEC_DOWN_INTR, 3 => SECOND_DOWN_INTR, 4 => TIMER1_TICK, 5 => PS2_INT, 6 => IOCTL_RDINT, 7 => IOCTL_WRINT, 8 => UART0_RX_INTR, 9 => UART0_TX_INTR, 10 => UART1_RX_INTR, 11 => UART1_TX_INTR, others => '0'); INT_TRIGGER <= INT_REQ; INTR0_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "10110000" -- Interrupt Range 0xFFFFFBxx, 0xB00-B0F else '0'; else generate IO_DATA_READ_INTRCTL <= (others => 'X'); INT_TRIGGER <= '0'; INT_ENABLE <= (others => '0'); IO_WAIT_INTR <= '0'; end generate; -- UART UART0 : entity work.uart generic map ( RX_FIFO_BIT_DEPTH => MAX_RX_FIFO_BITS, TX_FIFO_BIT_DEPTH => MAX_TX_FIFO_BITS, COUNTER_BITS => 16, BAUDCLK_FREQUENCY => SYSCLK_FREQUENCY ) port map ( -- CPU Interface CLK => SYSCLK, -- memory master clock RESET => not RESET_n, -- high active sync reset ADDR => MEM_ADDR(3 downto 2), -- 0 = Read/Write Data, 1 = Control Register, 3 = Baud Register DATA_IN => MEM_DATA_WRITE, -- write data DATA_OUT => UART0_DATA_OUT, -- read data CS => UART0_CS, -- Chip Select. WREN => MEM_WRITE_ENABLE, -- Write enable. RDEN => MEM_READ_ENABLE, -- Read enable. -- IRQ outputs TXINTR => UART0_TX_INTR, -- Tx buffer empty interrupt. RXINTR => UART0_RX_INTR, -- Rx buffer full interrupt. -- Serial data TXD => UART_TX_0, RXD => UART_RX_0 ); UART1 : entity work.uart generic map ( RX_FIFO_BIT_DEPTH => MAX_RX_FIFO_BITS, TX_FIFO_BIT_DEPTH => MAX_TX_FIFO_BITS, COUNTER_BITS => 16, BAUDCLK_FREQUENCY => SYSCLK_FREQUENCY ) port map ( -- CPU Interface CLK => SYSCLK, -- memory master clock RESET => not RESET_n, -- high active sync reset ADDR => MEM_ADDR(3 downto 2), -- 0 = Read/Write Data, 1 = Control Register, 3 = Baud Register DATA_IN => MEM_DATA_WRITE, -- write data DATA_OUT => UART1_DATA_OUT, -- read data CS => UART1_CS, -- Chip Select. WREN => MEM_WRITE_ENABLE, -- Write enable. RDEN => MEM_READ_ENABLE, -- Read enable. -- IRQ outputs TXINTR => UART1_TX_INTR, -- Tx buffer empty interrupt. RXINTR => UART1_RX_INTR, -- Rx buffer full interrupt. -- Serial data TXD => UART1_TX, RXD => UART_RX_1 ); -- IO Control Bus controller. IOCTL: if SOC_IMPL_IOCTL = true and (BOARD_DE10 = true or BOARD_CYC1000 = true) generate IOCTL0 : entity work.IOCTL port map ( CLK => SYSCLK, -- memory master clock RESET => not RESET_n, -- high active sync reset ADDR => MEM_ADDR(4 downto 2), -- address bus. DATA_IN => MEM_DATA_WRITE, -- write data DATA_OUT => IOCTL_DATA_OUT, -- read data CS => IOCTL_CS, -- Chip Select. WREN => MEM_WRITE_ENABLE, -- Write enable. RDEN => MEM_READ_ENABLE, -- Read enable. -- IRQ outputs -- IRQ_RD_O => IOCTL_RDINT, -- Read Interrupts from IOCTL. IRQ_WR_O => IOCTL_WRINT, -- Write Interrupts from IOCTL. -- IOCTL Bus -- IOCTL_DOWNLOAD => IOCTL_DOWNLOAD, -- Downloading to FPGA. IOCTL_UPLOAD => IOCTL_UPLOAD, -- Uploading from FPGA. IOCTL_CLK => IOCTL_CLK, -- I/O Clock. IOCTL_WR => IOCTL_WR, -- Write Enable to FPGA. IOCTL_RD => IOCTL_RD, -- Read Enable from FPGA. IOCTL_SENSE => IOCTL_SENSE, -- Sense to see if HPS accessing ioctl bus. IOCTL_SELECT => IOCTL_SELECT, -- Enable IOP control over ioctl bus. IOCTL_ADDR => IOCTL_ADDR, -- Address in FPGA to write into. IOCTL_DOUT => IOCTL_DOUT, -- Data to be written into FPGA. IOCTL_DIN => IOCTL_DIN -- Data to be read into HPS. ); process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then IO_WAIT_IOCTL <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then IO_WAIT_IOCTL <= '0'; -- CPU Write? if MEM_WRITE_ENABLE = '1' and IO_SELECT = '1' then -- IO Read? elsif MEM_READ_ENABLE = '1' and IO_SELECT = '1' then if IOCTL_CS = '1' then IO_DATA_READ_IOCTL <= IOCTL_DATA_OUT; end if; end if; end if; -- rising-edge(SYSCLK) end process; IOCTL_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 4) = "10000000" -- Ioctl Range 0xFFFFF8xx 0x800-80F else '0'; else generate IOCTL_CS <= '0'; IO_WAIT_IOCTL <= '0'; IOCTL_RDINT <= '0'; IOCTL_WRINT <= '0'; end generate; IMPLSOCCFG: if SOC_IMPL_SOCCFG = true generate process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then -- SoC Configuration. IO_DATA_READ_SOCCFG <= (others => 'X'); case MEM_ADDR(7 downto 2) is when "000000" => -- ZPU Id IO_DATA_READ_SOCCFG(31 downto 28) <= "1010"; -- Identifier to show SoC Configuration registers are implemented. if ZPU_SMALL = 1 then IO_DATA_READ_SOCCFG(15 downto 0) <= std_logic_vector(to_unsigned(ZPU_ID_SMALL, 16)); elsif ZPU_MEDIUM = 1 then IO_DATA_READ_SOCCFG(15 downto 0) <= std_logic_vector(to_unsigned(ZPU_ID_MEDIUM, 16)); elsif ZPU_FLEX = 1 then IO_DATA_READ_SOCCFG(15 downto 0) <= std_logic_vector(to_unsigned(ZPU_ID_FLEX, 16)); elsif ZPU_EVO = 1 then IO_DATA_READ_SOCCFG(15 downto 0) <= std_logic_vector(to_unsigned(ZPU_ID_EVO, 16)); elsif ZPU_EVO_MINIMAL = 1 then IO_DATA_READ_SOCCFG(15 downto 0) <= std_logic_vector(to_unsigned(ZPU_ID_EVO_MINIMAL, 16)); else IO_DATA_READ_SOCCFG(15 downto 0) <= (others => '0'); end if; when "000001" => -- System Frequency IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SYSCLK_FREQUENCY, wordSize)); when "000010" => -- Sysbus Memory Frequency if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and SOC_IMPL_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_SDRAM_CLK_FREQ, wordSize)); else IO_DATA_READ_SOCCFG <= (others => '0'); end if; when "000011" => -- Wishbone Memory Frequency if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_WB = true and SOC_IMPL_WB_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_WB_SDRAM_CLK_FREQ, wordSize)); else IO_DATA_READ_SOCCFG <= (others => '0'); end if; when "000100" => -- Devices Implemented IO_DATA_READ_SOCCFG(22 downto 0) <= to_std_logic(SOC_IMPL_WB) & to_std_logic(SOC_IMPL_WB_SDRAM) & to_std_logic(SOC_IMPL_WB_I2C) & to_std_logic(SOC_IMPL_BRAM) & to_std_logic(SOC_IMPL_RAM) & to_std_logic(SOC_IMPL_INSN_BRAM) & to_std_logic(SOC_IMPL_SDRAM) & to_std_logic(SOC_IMPL_IOCTL) & to_std_logic(SOC_IMPL_PS2) & to_std_logic(SOC_IMPL_SPI) & to_std_logic(SOC_IMPL_SD) & std_logic_vector(to_unsigned(SOC_SD_DEVICES, 2)) & to_std_logic(SOC_IMPL_INTRCTL) & std_logic_vector(to_unsigned(SOC_INTR_MAX, 5)) & to_std_logic(SOC_IMPL_TIMER1) & std_logic_vector(to_unsigned(2**SOC_TIMER1_COUNTERS, 3)); when "000101" => -- BRAM Address if SOC_IMPL_BRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_START, wordSize)); end if; when "000110" => -- BRAM Size if SOC_IMPL_BRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_BRAM_END - SOC_ADDR_BRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "000111" => -- RAM Address if SOC_IMPL_RAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_RAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001000" => -- RAM Size if SOC_IMPL_RAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_RAM_END - SOC_ADDR_RAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001001" => -- Instruction BRAM Address if SOC_IMPL_INSN_BRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_INSN_BRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001010" => -- Instruction BRAM Size if SOC_IMPL_INSN_BRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_INSN_BRAM_END - SOC_ADDR_INSN_BRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001011" => -- SDRAM Address if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and SOC_IMPL_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_SDRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => '0'); end if; when "001100" => -- SDRAM Size if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1 or ZPU_MEDIUM = 1) and SOC_IMPL_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_SDRAM_END - SOC_ADDR_SDRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => '0'); end if; when "001101" => -- WB SDRAM Address if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_WB = true and SOC_IMPL_WB_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_WB_SDRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001110" => -- WB SDRAM Size if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_WB = true and SOC_IMPL_WB_SDRAM = true then IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_ADDR_WB_SDRAM_END - SOC_ADDR_WB_SDRAM_START, wordSize)); else IO_DATA_READ_SOCCFG <= (others => 'X'); end if; when "001111" => -- CPU Reset Address IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_RESET_ADDR_CPU, wordSize)); when "010000" => -- CPU Memory Start Address IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_START_ADDR_MEM, wordSize)); when "010001" => -- Stack Start Address IO_DATA_READ_SOCCFG <= std_logic_vector(to_unsigned(SOC_STACK_ADDR, wordSize)); when others => end case; end if; -- rising-edge(SYSCLK) end process; SOCCFG_CS <= '1' when IO_SELECT = '1' and MEM_ADDR(11 downto 8) = "1111" -- SoC Config Range 0xF00-FF0, step 4 for 32 bit registers. else '0'; else generate IO_DATA_READ_SOCCFG <= (others => '0'); end generate; ------------------------------------------------------------------------------------ -- END Direct I/O devices ------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------ -- WISHBONE devices ------------------------------------------------------------------------------------ I2C : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and EVO_USE_WB_BUS = true and SOC_IMPL_WB_I2C = true generate I2C_MASTER_0: work.i2c_master_top generic map ( ARST_LVL => '1' -- asynchronous reset level ) port map ( -- Wishbone Bus wb_clk_i => SYSCLK, -- master clock input wb_rst_i => not RESET_n, -- synchronous active high reset arst_i => '0', -- asynchronous reset - not used. wb_adr_i => WB_ADR_O(4 downto 2), -- lower address bits wb_dat_i => WB_DAT_O(BYTE_RANGE), -- Databus input (lowest 8 bit) wb_dat_o => WB_DATA_READ_I2C(BYTE_RANGE), -- Databus output wb_we_i => WB_WE_O, -- Write enable input wb_stb_i => WB_I2C_CS, -- Strobe signal using chip select. wb_cyc_i => WB_CYC_O, -- Valid bus cycle input wb_ack_o => WB_I2C_ACK, -- Bus cycle acknowledge output wb_inta_o => WB_I2C_IRQ, -- interrupt request output signal -- I²C lines scl_pad_i => SCL_PAD_IN, -- i2c clock line input scl_pad_o => SCL_PAD_OUT, -- i2c clock line output scl_padoen_o => SCL_PAD_OE, -- i2c clock line output enable, active low sda_pad_i => SDA_PAD_IN, -- i2c data line input sda_pad_o => SDA_PAD_OUT, -- i2c data line output sda_padoen_o => SDA_PAD_OE -- i2c data line output enable, active low ); -- Data Width Adaption, I2C is only 8 bits so expand to 32bits. --WB_DATA_READ_I2C <= x"000000" & I2C_DATA_OUT; -- IO Buffer I2C_SCL_IO <= SCL_PAD_OUT when (SCL_PAD_OE = '0') else 'Z'; I2C_SDA_IO <= SDA_PAD_OUT when (SDA_PAD_OE = '0') else 'Z'; SCL_PAD_IN <= I2C_SCL_IO; SDA_PAD_IN <= I2C_SDA_IO; -- Halt / Error WB_I2C_HALT <= '0'; -- no throttle -> full speed WB_I2C_ERR <= '0'; -- nothing can go wrong - never ever! else generate I2C_SCL_IO <= 'Z'; I2C_SDA_IO <= 'Z'; SCL_PAD_IN <= 'X'; SDA_PAD_IN <= 'X'; WB_I2C_HALT <= '0'; WB_I2C_ERR <= '0'; end generate; -- SDRAM over WishBone bus. ZPUWBSDRAMEVO : if (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and SOC_IMPL_WB = true and SOC_IMPL_WB_SDRAM = true and (BOARD_QMV = true or BOARD_CYC1000 = true) generate ZPUWBSDRAM : entity work.WBSDRAM generic map ( SDRAM_ROWS => SOC_WB_SDRAM_ROWS, -- Number of Rows in the SDRAM. SDRAM_COLUMNS => SOC_WB_SDRAM_COLUMNS, -- Number of Columns in an SDRAM page (ie. 1 row). SDRAM_BANKS => SOC_WB_SDRAM_BANKS, -- Number of banks in the SDRAM. SDRAM_DATAWIDTH => SOC_WB_SDRAM_DATAWIDTH, -- Data width of SDRAM chip (ie. 16, 32). SDRAM_CLK_FREQ => SOC_WB_SDRAM_CLK_FREQ, -- Frequency of SDRAM clock in Hertz. SDRAM_tRCD => SOC_WB_SDRAM_tRCD, -- tRCD - RAS to CAS minimum period (in ns), ie. 20ns -> 2 cycles@100MHz SDRAM_tRP => SOC_WB_SDRAM_tRP, -- tRP - Precharge delay, min time for a precharge command to complete (in ns), ie. 15ns -> 2 cycles@100MHz SDRAM_tRFC => SOC_WB_SDRAM_tRFC, -- tRFC - Auto-refresh minimum time to complete (in ns), ie. 66ns SDRAM_tREF => SOC_WB_SDRAM_tREF -- tREF - period of time a complete refresh of all rows is made within (in ms). ) port map ( -- SDRAM Interface SDRAM_CLK => MEMCLK, -- sdram clock running at an offset from system clock. SDRAM_RST => not RESET_n, -- reset the sdram controller. SDRAM_CKE => SDRAM_CKE, -- clock enable. SDRAM_DQ => SDRAM_DQ, -- 16 bit bidirectional data bus SDRAM_ADDR => SDRAM_ADDR, -- 12 bit multiplexed address bus SDRAM_DQM => SDRAM_DQM, -- two byte masks SDRAM_BA => SDRAM_BA, -- two banks SDRAM_CS_n => SDRAM_CS_n, -- a single chip select SDRAM_WE_n => SDRAM_WE_n, -- write enable SDRAM_RAS_n => SDRAM_RAS_n, -- row address select SDRAM_CAS_n => SDRAM_CAS_n, -- columns address select SDRAM_READY => SDRAM_READY, -- sd ready. -- WishBone interface. WB_CLK => WB_CLK_I, -- clock to which sdram state machine is synchonized WB_RST_I => not RESET_n, -- Reset baased on CPU reset active high. WB_DATA_I => WB_DAT_O, -- data input from chipset/cpu WB_DATA_O => WB_DATA_READ_SDRAM, -- data output to chipset/cpu WB_ACK_O => WB_SDRAM_ACK, WB_ADR_I => WB_ADR_O(ADDR_BIT_WB_SDRAM_RANGE), -- lower 2 bits are ignored. WB_SEL_I => WB_SEL_O, WB_CTI_I => WB_CTI_O, -- cycle type. WB_STB_I => WB_SDRAM_STB, WB_CYC_I => WB_CYC_O, -- cpu/chipset requests cycle WB_WE_I => WB_SDRAM_WREN, -- cpu/chipset requests write WB_TGC_I => "0000000", -- cycle tag WB_HALT_O => open, WB_ERR_O => open ); -- -- ZPUSRAM: entity work.SRAM -- generic map ( -- addrbits => 14 -- ) -- port map ( -- -- WishBone interface. -- WB_CLK_I => WB_CLK_I, -- 100MHz chipset clock to which sdram state machine is synchonized -- WB_RST_I => not RESET_n, -- high active sync reset -- WB_DATA_I => WB_DAT_O, -- data input from chipset/cpu -- WB_DATA_O => WB_DATA_READ_SDRAM, -- data output to chipset/cpu -- WB_ACK_O => WB_SDRAM_ACK, -- WB_ADR_I => WB_ADR_O(13 downto 0), -- lower 2 bits are ignored. -- WB_SEL_I => WB_SEL_O, -- WB_CTI_I => WB_CTI_O, -- cycle type. -- WB_STB_I => WB_SDRAM_STB, -- WB_CYC_I => WB_CYC_O, -- cpu/chipset requests cycle -- WB_WE_I => RAM_WREN, -- cpu/chipset requests write -- WB_TGC_I => "0000000", -- cycle tag -- WB_HALT_O => open, -- WB_ERR_O => open -- ); -- RAM Range SOC_ADDR_RAM_START) -> SOC_ADDR_RAM_END WB_SDRAM_SELECT <= '1' when (ZPU_EVO = 1 or ZPU_EVO_MINIMAL = 1) and (WB_ADR_O >= std_logic_vector(to_unsigned(SOC_ADDR_WB_SDRAM_START, WB_ADR_O'LENGTH)) and WB_ADR_O < std_logic_vector(to_unsigned(SOC_ADDR_WB_SDRAM_END, WB_ADR_O'LENGTH))) else '0'; -- Enable write to RAM when selected and CPU in write state. WB_SDRAM_WREN <= '1' when WB_SDRAM_SELECT = '1' and WB_WE_O = '1' else '0'; -- Wishbone strobe based on the RAM Select signal which limits the address range. WB_SDRAM_STB <= '1' when WB_SDRAM_SELECT = '1' and WB_STB_O = '1' else '0'; -- SDRAM clock based on system clock. SDRAM_CLK <= MEMCLK; else generate WB_SDRAM_SELECT <= '0'; WB_SDRAM_WREN <= '0'; WB_SDRAM_STB <= '0'; SDRAM_CLK <= MEMCLK; end generate; ------------------------------------------------------------------------------------ -- END WISHBONE devices ------------------------------------------------------------------------------------ -- Reset counter. Incoming reset toggles reset and holds it low for a fixed period. Additionally, if the primary UART RX receives a break -- signal, then the reset is triggered. -- process(SYSCLK, RESET_IN) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_IN='0' then RESET_COUNTER <= X"FFFF"; RESET_COUNTER_RX <= to_unsigned(((SYSCLK_FREQUENCY)/300), 16); RESET_n <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then -- Edge detection for read signal. Most I/O operations need a read signal longer than 1 clock so BUSY needs to be asserted in order to prolong the read cycle. -- MEM_READ_ENABLE_LAST <= MEM_READ_ENABLE; -- If the RX receives a break signal, count down to ensure it is held low for correct period, when the count reaches -- zero, start a reset. -- if UART_RX_0 = '0' or UART_RX_1 = '0' then RESET_COUNTER_RX <= RESET_COUNTER_RX - 1; else RESET_COUNTER_RX <= to_unsigned(((SYSCLK_FREQUENCY)/300), 16); end if; if RESET_COUNTER_RX = X"0000" then RESET_COUNTER <= X"FFFF"; RESET_COUNTER_RX <= to_unsigned(((SYSCLK_FREQUENCY)/300), 16); RESET_n <= '0'; end if; RESET_COUNTER <= RESET_COUNTER - 1; if RESET_COUNTER = X"0000" then RESET_n <= '1'; end if; end if; end process; -- Main peripheral process, decode address and activate memory/peripheral accordingly. process(SYSCLK, RESET_n) begin ------------------------ -- HIGH LEVEL -- ------------------------ ------------------------ -- ASYNCHRONOUS RESET -- ------------------------ if RESET_n='0' then MICROSEC_DOWN_COUNTER <= (others => '0'); MILLISEC_DOWN_COUNTER <= (others => '0'); MILLISEC_UP_COUNTER <= (others => '0'); SECOND_DOWN_COUNTER <= (others => '0'); MICROSEC_DOWN_TICK <= 0; MILLISEC_DOWN_TICK <= 0; SECOND_DOWN_TICK <= 0; MILLISEC_UP_TICK <= 0; MICROSEC_DOWN_INTR <= '0'; MICROSEC_DOWN_INTR_EN <= '0'; MILLISEC_DOWN_INTR <= '0'; MILLISEC_DOWN_INTR_EN <= '0'; SECOND_DOWN_INTR <= '0'; SECOND_DOWN_INTR_EN <= '0'; RTC_MICROSEC_TICK <= 0; RTC_MICROSEC_COUNTER <= 0; RTC_MILLISEC_COUNTER <= 0; RTC_SECOND_COUNTER <= 0; RTC_MINUTE_COUNTER <= 0; RTC_HOUR_COUNTER <= 0; RTC_DAY_COUNTER <= 1; RTC_MONTH_COUNTER <= 1; RTC_YEAR_COUNTER <= 0; RTC_TICK_HALT <= '0'; ----------------------- -- RISING CLOCK EDGE -- ----------------------- elsif rising_edge(SYSCLK) then -- CPU Write? if MEM_WRITE_ENABLE = '1' and IO_SELECT = '1' then -- Write to Millisecond Timer - set current time and day. if TIMER0_CS = '1' then case MEM_ADDR(5 downto 2) is when "0000" => MICROSEC_DOWN_COUNTER(23 downto 0) <= unsigned(MEM_DATA_WRITE(23 downto 0)); MICROSEC_DOWN_TICK <= 0; when "0001" => MILLISEC_DOWN_COUNTER(17 downto 0) <= unsigned(MEM_DATA_WRITE(17 downto 0)); MILLISEC_DOWN_TICK <= 0; when "0010" => MILLISEC_UP_COUNTER(31 downto 0) <= unsigned(MEM_DATA_WRITE(31 downto 0)); MILLISEC_UP_TICK <= 0; when "0011" => SECOND_DOWN_COUNTER(11 downto 0) <= unsigned(MEM_DATA_WRITE(11 downto 0)); SECOND_DOWN_TICK <= 0; when "0111" => RTC_TICK_HALT <= MEM_DATA_WRITE(0); when "1000" => RTC_MICROSEC_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(9 downto 0))); RTC_MICROSEC_TICK <= 0; when "1001" => RTC_MILLISEC_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(9 downto 0))); RTC_MICROSEC_TICK <= 0; when "1010" => RTC_SECOND_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(5 downto 0))); RTC_MICROSEC_TICK <= 0; when "1011" => RTC_MINUTE_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(5 downto 0))); RTC_MICROSEC_TICK <= 0; when "1100" => RTC_HOUR_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(4 downto 0))); RTC_MICROSEC_TICK <= 0; when "1101" => RTC_DAY_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(3 downto 0))); RTC_MICROSEC_TICK <= 0; when "1110" => RTC_MONTH_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(3 downto 0))); RTC_MICROSEC_TICK <= 0; when "1111" => RTC_YEAR_COUNTER <= to_integer(unsigned(MEM_DATA_WRITE(11 downto 0))); RTC_MICROSEC_TICK <= 0; when others => end case; end if; end if; -- Read from UART. if UART0_CS = '1' then IO_DATA_READ <= UART0_DATA_OUT; end if; if UART1_CS = '1' then IO_DATA_READ <= UART1_DATA_OUT; end if; -- Read from millisecond timer, read milliseconds in last 24 hours and number of elapsed days. if TIMER0_CS = '1' then IO_DATA_READ <= (others => '0'); case MEM_ADDR(5 downto 2) is when "0000" => IO_DATA_READ(23 downto 0) <= std_logic_vector(MICROSEC_DOWN_COUNTER(23 downto 0)); when "0001" => IO_DATA_READ(17 downto 0) <= std_logic_vector(MILLISEC_DOWN_COUNTER(17 downto 0)); when "0010" => IO_DATA_READ(31 downto 0) <= std_logic_vector(MILLISEC_UP_COUNTER(31 downto 0)); when "0011" => IO_DATA_READ(11 downto 0) <= std_logic_vector(SECOND_DOWN_COUNTER(11 downto 0)); when "1000" => IO_DATA_READ(9 downto 0) <= std_logic_vector(to_unsigned(RTC_MICROSEC_COUNTER, 10)); when "1001" => IO_DATA_READ(9 downto 0) <= std_logic_vector(to_unsigned(RTC_MILLISEC_COUNTER, 10)); when "1010" => IO_DATA_READ(5 downto 0) <= std_logic_vector(to_unsigned(RTC_SECOND_COUNTER, 6)); when "1011" => IO_DATA_READ(5 downto 0) <= std_logic_vector(to_unsigned(RTC_MINUTE_COUNTER, 6)); when "1100" => IO_DATA_READ(4 downto 0) <= std_logic_vector(to_unsigned(RTC_HOUR_COUNTER, 5)); when "1101" => IO_DATA_READ(4 downto 0) <= std_logic_vector(to_unsigned(RTC_DAY_COUNTER, 5)); when "1110" => IO_DATA_READ(3 downto 0) <= std_logic_vector(to_unsigned(RTC_MONTH_COUNTER, 4)); when "1111" => IO_DATA_READ(11 downto 0) <= std_logic_vector(to_unsigned(RTC_YEAR_COUNTER, 12)); when others => end case; end if; -- Timer in microseconds, Each 24 hours the timer is zeroed and the day counter incremented. Used for delay loops -- and RTC. if RTC_TICK_HALT = '0' then RTC_MICROSEC_TICK <= RTC_MICROSEC_TICK+1; end if; if RTC_MICROSEC_TICK = ((SYSCLK_FREQUENCY/1000000) -1) then -- Sys clock has to be > 1MHz or will not be accurate. RTC_MICROSEC_TICK <= 0; RTC_MICROSEC_COUNTER <= RTC_MICROSEC_COUNTER + 1; if RTC_MICROSEC_COUNTER = (1000 - 1) then RTC_MICROSEC_COUNTER <= 0; RTC_MILLISEC_COUNTER <= RTC_MILLISEC_COUNTER + 1; if RTC_MILLISEC_COUNTER = (1000 - 1) then RTC_SECOND_COUNTER <= RTC_SECOND_COUNTER + 1; RTC_MILLISEC_COUNTER <= 0; if RTC_SECOND_COUNTER = (60 - 1) then RTC_MINUTE_COUNTER <= RTC_MINUTE_COUNTER + 1; RTC_SECOND_COUNTER <= 0; if RTC_MINUTE_COUNTER = (60 - 1) then RTC_HOUR_COUNTER <= RTC_HOUR_COUNTER + 1; RTC_MINUTE_COUNTER <= 0; if RTC_HOUR_COUNTER = (24 - 1) then RTC_DAY_COUNTER <= RTC_DAY_COUNTER + 1; RTC_HOUR_COUNTER <= 0; if (RTC_DAY_COUNTER = 31 and (RTC_MONTH_COUNTER = 4 or RTC_MONTH_COUNTER = 6 or RTC_MONTH_COUNTER = 9 or RTC_MONTH_COUNTER = 11)) or (RTC_DAY_COUNTER = 32 and RTC_MONTH_COUNTER /= 4 and RTC_MONTH_COUNTER /= 6 and RTC_MONTH_COUNTER /= 9 and RTC_MONTH_COUNTER /= 11) or (RTC_DAY_COUNTER = 29 and RTC_MONTH_COUNTER = 2 and std_logic_vector(to_unsigned(RTC_YEAR_COUNTER, 2)) /= "00") or (RTC_DAY_COUNTER = 30 and RTC_MONTH_COUNTER = 2 and std_logic_vector(to_unsigned(RTC_YEAR_COUNTER, 2)) = "00") then RTC_MONTH_COUNTER <= RTC_MONTH_COUNTER + 1; RTC_DAY_COUNTER <= 1; if RTC_MONTH_COUNTER = 13 then RTC_YEAR_COUNTER <= RTC_YEAR_COUNTER + 1; RTC_MONTH_COUNTER <= 1; end if; end if; end if; end if; end if; end if; end if; end if; -- Down and up counters, each have independent ticks which reset on counter set, this guarantees timer is accurate. MICROSEC_DOWN_TICK <= MICROSEC_DOWN_TICK+1; if MICROSEC_DOWN_TICK = ((SYSCLK_FREQUENCY/1000000) -1) then -- Sys clock has to be > 1MHz or will not be accurate. MICROSEC_DOWN_TICK <= 0; -- Decrement microsecond down counter if not yet zero. if MICROSEC_DOWN_COUNTER /= 0 then MICROSEC_DOWN_COUNTER <= MICROSEC_DOWN_COUNTER - 1; end if; if MICROSEC_DOWN_COUNTER = 0 and MICROSEC_DOWN_INTR_EN = '1' then MICROSEC_DOWN_INTR <= '1'; end if; end if; MILLISEC_DOWN_TICK <= MILLISEC_DOWN_TICK+1; if MILLISEC_DOWN_TICK = (((SYSCLK_FREQUENCY/1000000)*1000) -1) then -- Sys clock has to be > 1MHz or will not be accurate. MILLISEC_DOWN_TICK <= 0; -- Decrement millisecond down counter if not yet zero. if MILLISEC_DOWN_COUNTER /= 0 then MILLISEC_DOWN_COUNTER <= MILLISEC_DOWN_COUNTER - 1; end if; if MILLISEC_DOWN_COUNTER = 0 and MILLISEC_DOWN_INTR_EN = '1' then MILLISEC_DOWN_INTR <= '1'; end if; end if; MILLISEC_UP_TICK <= MILLISEC_UP_TICK+1; if MILLISEC_UP_TICK = (((SYSCLK_FREQUENCY/1000000)*1000) - 1) then -- Sys clock has to be > 1MHz or will not be accurate. MILLISEC_UP_TICK <= 0; MILLISEC_UP_COUNTER <= MILLISEC_UP_COUNTER + 1; end if; SECOND_DOWN_TICK <= SECOND_DOWN_TICK+1; if SECOND_DOWN_TICK = (((SYSCLK_FREQUENCY/1000000)*1000000) - 1) then -- Sys clock has to be > 1MHz or will not be accurate. SECOND_DOWN_TICK <= 0; -- Decrement second down counter if not yet zero. if SECOND_DOWN_COUNTER /= 0 then SECOND_DOWN_COUNTER <= SECOND_DOWN_COUNTER - 1; end if; if SECOND_DOWN_COUNTER = 0 and SECOND_DOWN_INTR_EN = '1' then SECOND_DOWN_INTR <= '1'; end if; end if; end if; -- rising-edge(SYSCLK) end process; end architecture;