From b751730f873ecd68b096ef3757bf784fc26e3429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BC=D0=B0?= Date: Wed, 15 Jan 2025 00:30:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?/=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- divmmc.qpf | 30 +++++ divmmc.qsf | 124 +++++++++++++++++++++ divmmc.vhd | 279 ++++++++++++++++++++++++++++++++++++++++++++++ divmmc.vhd (orig) | 262 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 695 insertions(+) create mode 100644 divmmc.qpf create mode 100644 divmmc.qsf create mode 100644 divmmc.vhd create mode 100644 divmmc.vhd (orig) diff --git a/divmmc.qpf b/divmmc.qpf new file mode 100644 index 0000000..b50dddb --- /dev/null +++ b/divmmc.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition +# Date created = 22:40:48 September 08, 2020 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.0" +DATE = "22:40:48 September 08, 2020" + +# Revisions + +PROJECT_REVISION = "divmmc" diff --git a/divmmc.qsf b/divmmc.qsf new file mode 100644 index 0000000..aa5d301 --- /dev/null +++ b/divmmc.qsf @@ -0,0 +1,124 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition +# Date created = 22:40:48 September 08, 2020 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# divmmc_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY MAX7000S +set_global_assignment -name DEVICE "EPM7128STC100-7" +set_global_assignment -name TOP_LEVEL_ENTITY divmmc +set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name PROJECT_CREATION_TIME_DATE "22:40:48 SEPTEMBER 08, 2020" +set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name VHDL_FILE divmmc.vhd +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 100 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1" +set_global_assignment -name POWER_EXT_SUPPLY_VOLTAGE_TO_REGULATOR 3.3V +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name MAX7000_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 +set_global_assignment -name USE_CONFIGURATION_DEVICE ON +set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING OFF +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" + + + +set_location_assignment PIN_9 -to A[0] +set_location_assignment PIN_12 -to A[1] +set_location_assignment PIN_13 -to A[10] +set_location_assignment PIN_19 -to A[11] +set_location_assignment PIN_80 -to A[12] +set_location_assignment PIN_79 -to A[13] +set_location_assignment PIN_77 -to A[14] +set_location_assignment PIN_76 -to A[15] +set_location_assignment PIN_14 -to A[2] +set_location_assignment PIN_17 -to A[3] +set_location_assignment PIN_20 -to A[4] +set_location_assignment PIN_22 -to A[5] +set_location_assignment PIN_24 -to A[6] +set_location_assignment PIN_25 -to A[7] +set_location_assignment PIN_23 -to A[8] +set_location_assignment PIN_21 -to A[9] + +set_location_assignment PIN_32 -to bankout[0] +set_location_assignment PIN_31 -to bankout[1] +set_location_assignment PIN_36 -to bankout[2] +set_location_assignment PIN_30 -to bankout[3] +set_location_assignment PIN_35 -to bankout[4] +set_location_assignment PIN_29 -to bankout[5] + +set_location_assignment PIN_47 -to card[0] +set_location_assignment PIN_46 -to card[1] + +set_location_assignment PIN_87 -to clock + +set_location_assignment PIN_7 -to d[0] +set_location_assignment PIN_5 -to d[1] +set_location_assignment PIN_1 -to d[2] +set_location_assignment PIN_99 -to d[3] +set_location_assignment PIN_100 -to d[4] +set_location_assignment PIN_2 -to d[5] +set_location_assignment PIN_6 -to d[6] +set_location_assignment PIN_8 -to d[7] + +set_location_assignment PIN_72 -to eprom + +set_location_assignment PIN_81 -to iorq +set_location_assignment PIN_92 -to m1 +set_location_assignment PIN_70 -to mapcondout +set_location_assignment PIN_10 -to mreq +set_location_assignment PIN_71 -to poweron + +set_location_assignment PIN_98 -to ramoe +set_location_assignment PIN_28 -to ramwr +set_location_assignment PIN_83 -to rd +set_location_assignment PIN_85 -to reset + + +set_location_assignment PIN_75 -to romcs +set_location_assignment PIN_16 -to romoe +set_location_assignment PIN_27 -to romwr + +set_location_assignment PIN_48 -to spi_clock +set_location_assignment PIN_50 -to spi_datain +set_location_assignment PIN_49 -to spi_dataout + +set_location_assignment PIN_84 -to wr + +set_location_assignment PIN_93 -to IORQGE +set_global_assignment -name SEARCH_PATH "h:\\zx\\cpld_project\\divmmc\\divmmc_cpld_v0\\output_files" \ No newline at end of file diff --git a/divmmc.vhd b/divmmc.vhd new file mode 100644 index 0000000..d53de88 --- /dev/null +++ b/divmmc.vhd @@ -0,0 +1,279 @@ +---------------------------------------------------------------------------------- +-- Inital version 1.0 for xc9572xl-vq64 +-- Engineer: Mario Prato +-- Create Date: 10:07:18 11/22/2012 +-- +-- Modified for Altera EPM3128ATC100-10 +-- Modified for Altera EPM7128STC100-7 +-- Engineer: valerium +-- Design Name: divmmc ver. 1.1 +-- Redesign Date: 02:54:18 10/05/2021 +-- +-- Module Name: divmmc - Behavioral +-- Project Name: divmmc +-- Target Devices: EPM3128ATC100-10 +-- Target Devices: EPM7128STC100-7 +-- Tool versions: Quartus II 13.0SP1 +-- Description: zx spectrum mmc sd interface +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity divmmc is +Port ( + +-- z80 cpu signals + A : in std_logic_vector (15 downto 0); + D : inout std_logic_vector (7 downto 0); + iorq : in std_logic; + IORQGE : out STD_LOGIC; + mreq : in std_logic; + wr : in std_logic; + rd : in std_logic; + m1 : in std_logic; + reset : in std_logic; + clock : in std_logic; -- Z80 Clock from ula chip (must be negated from edge connector signal) + +-- ram/rom signals + romcs : out STD_LOGIC; -- 1 -> page out spectrum rom + romoe : out STD_LOGIC; -- eeprom oe pin + romwr : out STD_LOGIC; -- eeprom wr pin + ramoe : out STD_LOGIC; -- ram oe pin + ramwr : out STD_LOGIC; -- ram wr pin + bankout : out STD_LOGIC_VECTOR (5 downto 0); --ram bank no. + +-- spi interface + card : out std_logic_vector(1 downto 0) :="11"; -- Cards CS + spi_clock : out std_logic :='1'; -- card clock + spi_dataout : out std_logic :='1'; -- card data in + spi_datain : in std_logic :='1'; -- card data out + +-- various + poweron : in STD_LOGIC; -- low pulse on poweron + eprom : in STD_LOGIC; -- eprom jumper + mapcondout : out std_logic -- hi when divmmc mem paged in +); +end divmmc; + +-- ============================================================================================================ + +architecture Behavioral of divmmc is + + signal address : std_logic_vector(7 downto 0) ; + signal zxmmcio : std_logic; + signal divideio : std_logic; + + signal bank : std_logic_vector (5 downto 0) := "000000"; + + signal mapterm : std_logic := '0'; + signal mapcond : std_logic := '0'; + signal conmem : std_logic := '0'; + signal mapram : std_logic := '0'; + signal automap : std_logic := '0'; + + signal map3DXX : std_logic; + signal map1F00 : std_logic; + + signal bank3 : std_logic; + + +-- Transmission states + type transStates is ( + IDLE, -- Wait for a WR or RD request on port 0xEB + SAMPLE, -- As there is an I/O request, prepare the transmission; sample the CPU databus if required + TRANSMIT); -- Transmission (SEND or RECEIVE) + signal transState : transStates := IDLE; -- Transmission state (initially IDLE) + + signal TState : unsigned(3 downto 0) := (others => '0'); -- Counts the T-States during transmission + + signal fromSDByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte received from SD + signal toSDByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte to send to SD + signal toCPUByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte seen by the CPU after a byte read + +-- dichiarazioni constanti + + constant divide_control_port : std_logic_vector(7 downto 0) := x"E3"; -- port %11100011 + constant zxmmc_control_port : std_logic_vector(7 downto 0) := x"E7"; -- era la porta 31 nella zxmmc+ + constant zxmmc_spi_port : std_logic_vector(7 downto 0) := x"EB"; -- era la porta 63 nella zxmmc+ + + +attribute PWR_MODE: string; +attribute FAST: string; +attribute BUFG: string; + +-- ============================================================================================================ + +begin + + address <= A(7 downto 0); + + bank3 <= '1' when bank ="000011" else '0'; + + + IORQGE <= '1' when (address = divide_control_port) OR (address = zxmmc_control_port) OR (address = zxmmc_spi_port) else 'Z'; + -- IORQGE for exUSSR clone's on NemoBUS + -- (SL60, SL62 socked, like ISA slot in x386 machines) + -- Need Hi-Z or VCC pinOut state (VCC=Blocked all ports in ZX mainboard) + + + -- ROM read write signals + + romoe <= rd or A(15) or A(14) or A(13) or (not conmem and mapram) or (not conmem and not automap) or (not conmem and eprom); + -- 5 OR Act.level=0; rd=0; A[15..13]=0; eprom=in_Pin; + + romcs <= '1' when ((automap and not eprom) or (automap and mapram) or conmem )='1' else '0' ; -- RDR NemoBUS + -- 3 OR Act.level=0; conmem=; inv.eprom=in_Pin; + + romwr <= '0' when wr ='0' and a(13)='0' and a(14)='0' and a(15)='0' and eprom='1' and conmem='1' else '1'; + -- 6 AND Act.level=0; inv.pin; A[15..13]=0; wr=0; eprom=1; conmem=Q_DFF; + + -- RAM read write signals + ramoe <= rd or A(15) or A(14) or ( not A(13) and not mapram) or ( not A(13) and conmem) or (not conmem and not automap) or (not conmem and eprom and not mapram); + + ramwr <= wr or A(15) or A(14) or not a(13) or (not conmem and mapram and bank3 ) or (not conmem and not automap) or (not conmem and eprom and not mapram); + + -- + -- Divide Automapping logic + + mapterm <= '1' when A(15 downto 0) = x"0000" or + A(15 downto 0) = x"0008" or + A(15 downto 0) = x"0038" or + A(15 downto 0) = x"0066" or + A(15 downto 0) = x"04c6" or + A(15 downto 0) = x"0562" else '0'; + + map3DXX <= '1' when A(15 downto 8) = "00111101" else '0'; -- mappa 3D00 - 3DFF + + map1F00 <= '0' when A(15 downto 3) = "0001111111111" else '1'; -- 1ff8 - 1fff + +-- ============================================================================================================ + process(mreq) + begin + + if falling_edge(mreq) then + if m1='0' then + mapcond <= mapterm or map3DXX or (mapcond and map1F00); + automap <= mapcond or map3DXX; + end if; + end if; + end process; + + mapcondout <= mapcond; -- Q_DFF_mapcond=Pin_out; + +-- divide control port + +divideio <='0' when iorq='0' and wr='0' and M1='1' and address = divide_control_port else '1'; --divideio=CLK_DFF's + -- 4 AND m1=1; iorq=0; wr=0; A[7..0]=hE3 adr. +-- ============================================================================================================ +process(divideio,poweron) + begin +-- if poweron ='0' then -- originally by M.Prato + if poweron ='0' or reset = '0' then -- patch by valerium + + bank <= "000000"; + mapram <= '0'; + conmem <= '0'; + + elsif rising_edge(divideio) then + + bank(5 downto 0) <= D(5 downto 0); + mapram <= D(6) or mapram; + conmem <= D(7); + end if; + +end process; +-- ============================================================================================================ +-- ram banks + + bankout(0) <= bank(0) or not A(13); -- Bank = 8kB + bankout(1) <= bank(1) or not A(13); + bankout(2) <= bank(2) and A(13); + bankout(3) <= bank(3) and A(13); + bankout(4) <= bank(4) and A(13); + bankout(5) <= bank(5) and A(13); + +-- SD CS signal management +zxmmcio <= '0' when address = zxmmc_control_port and iorq='0' and m1='1' and wr ='0' else '1'; + + + process(reset, zxmmcio) + begin + if reset = '0' then + card(0) <= '1'; -- Master SD VCC= no active + card(1) <= '1'; -- Slave SD + + elsif rising_edge(zxmmcio) then + + card(0) <= D(0); -- Master SD + card(1) <= D(1); -- Slave SD + + end if; + end process; + +-- ============================================================================================================ + +-- spi transmission/reception + + -- Update transmission state + process(clock, reset) + begin + if reset = '0' then + transState <= IDLE; + TState <= (others => '0'); + fromSDByte <= (others => '1'); + toSDByte <= (others => '1'); + toCPUByte <= (others => '1'); + + elsif falling_edge(clock) then + case transState is + + when IDLE => -- Intercept a new transmission request (port 0x3F) + if address = zxmmc_spi_port and iorq='0' and m1='1' then -- If there is a transmission request, prepare to SAMPLE the databus + transState <= SAMPLE; + end if; + + when SAMPLE => + if wr = '0' then -- If it is a SEND request, sample the CPU data bus + toSDByte <= D; + end if; + transState <= TRANSMIT; -- then start the transmission + + when TRANSMIT => + TState <= TState + 1; + + if TState < 15 then + + if TState(0) = '1' then + toSDByte <= toSDByte(6 downto 0)&'1'; + fromSDByte <= fromSDByte(6 downto 0)& spi_datain; + end if; + else + if TState = 15 then -- transmission is completed; intercept if there is a new transmission request + if address = zxmmc_spi_port and iorq='0' and m1='1'and wr='0' then + toSDByte <= D; + transState <= TRANSMIT; + else -- else we'll go in IDLE state. + transState <= IDLE; + -- TState <= "0000"; + end if; + toCPUByte <= fromSDByte(6 downto 0)& spi_datain; + end if; + end if; + when OTHERS => + null; + end case; + end if; + -- SPI SD Card pins + SPI_clock <= TState(0); + spi_dataout <= toSDByte(7); + end process; + + + + D <= toCPUByte when (address = zxmmc_spi_port) and (iorq = '0') and (rd = '0') and m1='1' else "ZZZZZZZZ"; + +-- ============================================================================================================ +end Behavioral; + diff --git a/divmmc.vhd (orig) b/divmmc.vhd (orig) new file mode 100644 index 0000000..97d5417 --- /dev/null +++ b/divmmc.vhd (orig) @@ -0,0 +1,262 @@ +---------------------------------------------------------------------------------- +-- Inital version 1.0 for xc9572xl-vq64 +-- Engineer: Mario Prato +-- Create Date: 10:07:18 11/22/2012 +-- +-- Modified for Altera EPM3128ATC100-10 +-- Engineer: valerium +-- Design Name: divmmc ver. 1.1 +-- Redesign Date: 02:54:18 10/05/2021 +-- +-- Module Name: divmmc - Behavioral +-- Project Name: divmmc +-- Target Devices: EPM3128ATC100-10 +-- Tool versions: Quartus II 13.0SP1 +-- Description: zx spectrum mmc sd interface +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity divmmc is +Port ( + +-- z80 cpu signals + A : in std_logic_vector (15 downto 0); + D : inout std_logic_vector (7 downto 0); + iorq : in std_logic; + mreq : in std_logic; + wr : in std_logic; + rd : in std_logic; + m1 : in std_logic; + reset : in std_logic; + clock : in std_logic; -- Z80 Clock from ula chip (must be negated from edge connector signal) + +-- ram/rom signals + romcs : out STD_LOGIC; -- 1 -> page out spectrum rom + romoe : out STD_LOGIC; -- eeprom oe pin + romwr : out STD_LOGIC; -- eeprom wr pin + ramoe : out STD_LOGIC; -- ram oe pin + ramwr : out STD_LOGIC; -- ram wr pin + bankout : out STD_LOGIC_VECTOR (5 downto 0); --ram bank no. + +-- spi interface + card : out std_logic_vector(1 downto 0) :="11"; -- Cards CS + spi_clock : out std_logic :='1'; -- card clock + spi_dataout : out std_logic :='1'; -- card data in + spi_datain : in std_logic :='1'; -- card data out + +-- various + poweron : in STD_LOGIC; -- low pulse on poweron + eprom : in STD_LOGIC; -- eprom jumper + mapcondout : out std_logic -- hi when divmmc mem paged in +); +end divmmc; + + +architecture Behavioral of divmmc is + + signal address : std_logic_vector(7 downto 0) ; + signal zxmmcio : std_logic; + signal divideio : std_logic; + + signal bank : std_logic_vector (5 downto 0) := "000000"; + + signal mapterm : std_logic := '0'; + signal mapcond : std_logic := '0'; + signal conmem : std_logic := '0'; + signal mapram : std_logic := '0'; + signal automap : std_logic := '0'; + + signal map3DXX : std_logic; + signal map1F00 : std_logic; + + signal bank3 : std_logic; + + +-- Transmission states + type transStates is ( + IDLE, -- Wait for a WR or RD request on port 0xEB + SAMPLE, -- As there is an I/O request, prepare the transmission; sample the CPU databus if required + TRANSMIT); -- Transmission (SEND or RECEIVE) + signal transState : transStates := IDLE; -- Transmission state (initially IDLE) + + signal TState : unsigned(3 downto 0) := (others => '0'); -- Counts the T-States during transmission + + signal fromSDByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte received from SD + signal toSDByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte to send to SD + signal toCPUByte : std_logic_vector(7 downto 0) := (others => '1'); -- Byte seen by the CPU after a byte read + +-- dichiarazioni constanti + + constant divide_control_port : std_logic_vector(7 downto 0) := x"E3"; -- port %11100011 + constant zxmmc_control_port : std_logic_vector(7 downto 0) := x"E7"; -- era la porta 31 nella zxmmc+ + constant zxmmc_spi_port : std_logic_vector(7 downto 0) := x"EB"; -- era la porta 63 nella zxmmc+ + + +attribute PWR_MODE: string; +attribute FAST: string; +attribute BUFG: string; + +begin + + address <= A(7 downto 0); + + bank3 <= '1' when bank ="000011" else '0'; + + -- ROM RAM read write signals + + + romoe <= rd or A(15) or A(14) or A(13) or (not conmem and mapram) or (not conmem and not automap) or (not conmem and eprom); + + romwr <= '0' when wr ='0' and a(13)='0' and a(14)='0' and a(15)='0' and eprom='1' and conmem='1' else '1'; + + ramoe <= rd or A(15) or A(14) or ( not A(13) and not mapram) or ( not A(13) and conmem) or (not conmem and not automap) or (not conmem and eprom and not mapram); + + ramwr <= wr or A(15) or A(14) or not a(13) or (not conmem and mapram and bank3 ) or (not conmem and not automap) or (not conmem and eprom and not mapram); + + romcs <= '1' when ((automap and not eprom) or (automap and mapram) or conmem )='1' else '0' ; + + -- + -- Divide Automapping logic + + mapterm <= '1' when A(15 downto 0) = x"0000" or + A(15 downto 0) = x"0008" or + A(15 downto 0) = x"0038" or + A(15 downto 0) = x"0066" or + A(15 downto 0) = x"04c6" or + A(15 downto 0) = x"0562" else '0'; + + map3DXX <= '1' when A(15 downto 8) = "00111101" else '0'; -- mappa 3D00 - 3DFF + + map1F00 <= '0' when A(15 downto 3) = "0001111111111" else '1'; -- 1ff8 - 1fff + + + process(mreq) + begin + + if falling_edge(mreq) then + if m1='0' then + mapcond <= mapterm or map3DXX or (mapcond and map1F00); + automap <= mapcond or map3DXX; + end if; + end if; + end process; + + mapcondout <= mapcond; + +-- divide control port + +divideio <='0' when iorq='0' and wr='0' and M1='1' and address = divide_control_port else '1'; + +process(divideio,poweron) + begin +-- if poweron ='0' then -- originally by M.Prato + if poweron ='0' or reset = '0' then -- patch by valerium + + bank <= "000000"; + mapram <= '0'; + conmem <= '0'; + + elsif rising_edge(divideio) then + + bank(5 downto 0) <= D(5 downto 0); + mapram <= D(6) or mapram; + conmem <= D(7); + end if; + +end process; + +-- ram banks + + bankout(0) <= bank(0) or not A(13); + bankout(1) <= bank(1) or not A(13); + bankout(2) <= bank(2) and A(13); + bankout(3) <= bank(3) and A(13); + bankout(4) <= bank(4) and A(13); + bankout(5) <= bank(5) and A(13); + +-- SD CS signal management +zxmmcio <= '0' when address = zxmmc_control_port and iorq='0' and m1='1' and wr ='0' else '1'; + + + process(reset, zxmmcio) + begin + if reset = '0' then + card(0) <= '1'; + card(1) <= '1'; + + elsif rising_edge(zxmmcio) then + + card(0) <= D(0); + card(1) <= D(1); + + end if; + end process; + + + +-- spi transmission/reception + + -- Update transmission state + process(clock, reset) + begin + if reset = '0' then + transState <= IDLE; + TState <= (others => '0'); + fromSDByte <= (others => '1'); + toSDByte <= (others => '1'); + toCPUByte <= (others => '1'); + + elsif falling_edge(clock) then + case transState is + + when IDLE => -- Intercept a new transmission request (port 0x3F) + if address = zxmmc_spi_port and iorq='0' and m1='1' then -- If there is a transmission request, prepare to SAMPLE the databus + transState <= SAMPLE; + end if; + + when SAMPLE => + if wr = '0' then -- If it is a SEND request, sample the CPU data bus + toSDByte <= D; + end if; + transState <= TRANSMIT; -- then start the transmission + + when TRANSMIT => + TState <= TState + 1; + + if TState < 15 then + + if TState(0) = '1' then + toSDByte <= toSDByte(6 downto 0)&'1'; + fromSDByte <= fromSDByte(6 downto 0)& spi_datain; + end if; + else + if TState = 15 then -- transmission is completed; intercept if there is a new transmission request + if address = zxmmc_spi_port and iorq='0' and m1='1'and wr='0' then + toSDByte <= D; + transState <= TRANSMIT; + else -- else we'll go in IDLE state. + transState <= IDLE; + -- TState <= "0000"; + end if; + toCPUByte <= fromSDByte(6 downto 0)& spi_datain; + end if; + end if; + when OTHERS => + null; + end case; + end if; + -- SPI SD Card pins + SPI_clock <= TState(0); + spi_dataout <= toSDByte(7); + end process; + + + + D <= toCPUByte when (address = zxmmc_spi_port) and (iorq = '0') and (rd = '0') and m1='1' else "ZZZZZZZZ"; + + +end Behavioral; +