From a6848924b25dbd34ac6f4570962f5fdf84989a74 Mon Sep 17 00:00:00 2001 From: dj Apendix Date: Tue, 9 Sep 2025 11:52:41 +0300 Subject: [PATCH] change vhd --- .../EPM3256_144/Custom_V1_0_0b/RTL/divmmc.vhd | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 CPLD/NemoBUS/EPM3256_144/Custom_V1_0_0b/RTL/divmmc.vhd diff --git a/CPLD/NemoBUS/EPM3256_144/Custom_V1_0_0b/RTL/divmmc.vhd b/CPLD/NemoBUS/EPM3256_144/Custom_V1_0_0b/RTL/divmmc.vhd new file mode 100644 index 0000000..cd03ae0 --- /dev/null +++ b/CPLD/NemoBUS/EPM3256_144/Custom_V1_0_0b/RTL/divmmc.vhd @@ -0,0 +1,271 @@ +---------------------------------------------------------------------------------- +-- Inital version 1.0 for xc9572xl-vq64 +-- Engineer: Mario Prato +-- Create Date: 10:07:18 11/22/2012 +-- +-- Modified for Altera EPM7128SLC84 *** +-- Redesign Date: 02:54:18 11/22/2020 +-- ReReDesing Date: 11:38 am 09/09/2025 +-- +-- Module Name: divmmc - Behavioral +-- Project Name: divmmc +-- Target Devices: EPM7128SLC84-15N +-- Tool versions: Quartus II 13.0SP1 +-- Description: zx spectrum mmc sd interface +-- Added IORQGE for NemoBUS (and ReName csrom to RDR) +-- +-- *** any CPLD/FPGA only needed In/Out pin defined +---------------------------------------------------------------------------------- +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; -- For exUSSR Clone ZX Spectrum (NemoBUS interface) + 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 + RDR : 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 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); + + RDR <= '1' when ((automap and not eprom) or (automap and mapram) or conmem )='1' else '0' ; -- RDR NemoBUS +-- 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 -- patched 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; +-- ============================================================================================================