diff --git a/VHDL/AppleIISd.vhd b/VHDL/AppleIISd.vhd index c270ea9..f8e3b3b 100644 --- a/VHDL/AppleIISd.vhd +++ b/VHDL/AppleIISd.vhd @@ -68,28 +68,58 @@ architecture Behavioral of AppleIISd is signal data_in : std_logic_vector (7 downto 0); signal data_out : std_logic_vector (7 downto 0); signal addr_low_int : std_logic_vector (1 downto 0); + signal s_spi_data_in : std_logic_vector(7 downto 0); + signal s_spi_data_out : std_logic_vector(7 downto 0); + signal s_bsy : std_logic; + signal s_tc : std_logic; + signal s_ece : std_logic; + signal s_frx : std_logic; signal data_en : std_logic; signal pgm_en : std_logic; + +component Registers is +Port ( + ADDR : in STD_LOGIC_VECTOR (1 downto 0); + BUS_DATA_IN : in STD_LOGIC_VECTOR (7 downto 0); + BUS_DATA_OUT : out STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA_IN : in STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA_OUT : out STD_LOGIC_VECTOR (7 downto 0); + + PGMEN : out STD_LOGIC; + ECE : out STD_LOGIC; + FRX : out STD_LOGIC; + SLAVESEL : out STD_LOGIC; + LED : out STD_LOGIC; + + BSY : in STD_LOGIC; + TC : in STD_LOGIC; + WP : in STD_LOGIC; + CARD : in STD_LOGIC; + NRESET : in STD_LOGIC; + NDEV_SEL : in STD_LOGIC; + IS_READ : in STD_LOGIC + ); +end component; component SpiController is Port ( - data_in : in std_logic_vector (7 downto 0); - data_out : out std_logic_vector (7 downto 0); - is_read : in std_logic; - nreset : in std_logic; - addr : in std_logic_vector (1 downto 0); - phi0 : in std_logic; - ndev_sel : in std_logic; - clk : in std_logic; - miso: in std_logic; - mosi : out std_logic; - sclk : out std_logic; - nsel : out std_logic; - wp : in std_logic; - card : in std_logic; - led : out std_logic; - pgm_en : out std_logic + BUS_DATA : in STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA : out STD_LOGIC_VECTOR (7 downto 0); + IS_READ : in STD_LOGIC; + NRESET : in STD_LOGIC; + ADDR : in STD_LOGIC_VECTOR (1 downto 0); + CLK_SLOW : in STD_LOGIC; + NDEV_SEL : in STD_LOGIC; + CLK_FAST : in STD_LOGIC; + MISO: in std_logic; + MOSI : out STD_LOGIC; + SCLK : out STD_LOGIC; + + BSY : out STD_LOGIC; + TC : out STD_LOGIC; + FRX : in std_logic; + ECE : in std_logic ); end component; @@ -114,23 +144,42 @@ end component; begin + regs: Registers port map( + ADDR => addr_low_int, + BUS_DATA_IN => data_in, + BUS_DATA_OUT => data_out, + SPI_DATA_IN => s_spi_data_in, + SPI_DATA_OUT => s_spi_data_out, + PGMEN => pgm_en, + ECE => s_ece, + FRX => s_frx, + SLAVESEL => NSEL, + LED => LED, + BSY => s_bsy, + TC => s_tc, + WP => WP, + CARD => CARD, + NRESET => NRESET, + NDEV_SEL => NDEV_SEL, + IS_READ => RNW + ); + spi: SpiController port map( - data_in => data_in, - data_out => data_out, - is_read => RNW, - nreset => NRESET, - addr => addr_low_int, - phi0 => PHI0, - ndev_sel => NDEV_SEL, - clk => CLK, - miso => MISO, - mosi => MOSI, - sclk => SCLK, - nsel => NSEL, - wp => WP, - card => CARD, - led => LED, - pgm_en => pgm_en + BUS_DATA => s_spi_data_out, + SPI_DATA => s_spi_data_in, + IS_READ => RNW, + NRESET => NRESET, + ADDR => addr_low_int, + CLK_SLOW => PHI0, + CLK_FAST => CLK, + NDEV_SEL => NDEV_SEL, + MISO => MISO, + MOSI => MOSI, + SCLK => SCLK, + BSY => s_bsy, + TC => s_tc, + FRX => s_frx, + ECE => s_ece ); addDec: AddressDecoder port map( diff --git a/VHDL/AppleIISd_PC44.xise b/VHDL/AppleIISd_PC44.xise index 782e8fe..0df5123 100644 --- a/VHDL/AppleIISd_PC44.xise +++ b/VHDL/AppleIISd_PC44.xise @@ -24,7 +24,7 @@ - + @@ -32,12 +32,16 @@ - + + + + + @@ -105,7 +109,7 @@ - + @@ -114,7 +118,7 @@ - + diff --git a/VHDL/Registers.vhd b/VHDL/Registers.vhd new file mode 100644 index 0000000..ab6ddc8 --- /dev/null +++ b/VHDL/Registers.vhd @@ -0,0 +1,138 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 20:04:43 04/08/2019 +-- Design Name: +-- Module Name: Registers - Behavioral +-- Project Name: +-- Target Devices: +-- Tool versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +--use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity Registers is + Port ( ADDR : in STD_LOGIC_VECTOR (1 downto 0); + BUS_DATA_IN : in STD_LOGIC_VECTOR (7 downto 0); + BUS_DATA_OUT : out STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA_IN : in STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA_OUT : out STD_LOGIC_VECTOR (7 downto 0); + + PGMEN : out STD_LOGIC; + ECE : out STD_LOGIC; + FRX : out STD_LOGIC; + SLAVESEL : out STD_LOGIC; + LED : out STD_LOGIC; + + BSY : in STD_LOGIC; + TC : in STD_LOGIC; + WP : in STD_LOGIC; + CARD : in STD_LOGIC; + NRESET : in STD_LOGIC; + NDEV_SEL : in STD_LOGIC; + IS_READ : in STD_LOGIC); + +end Registers; + +architecture Behavioral of Registers is + + signal s_pgmen : STD_LOGIC; + signal s_ece : STD_LOGIC; + signal s_frx : STD_LOGIC; + signal s_slavesel : STD_LOGIC; + signal s_sdhc : STD_LOGIC; + signal s_inited : STD_LOGIC; +begin + + PGMEN <= s_pgmen; + ECE <= s_ece; + FRX <= s_frx; + SLAVESEL <= s_slavesel; + LED <= not (BSY or not s_slavesel); + + -------------------------- + -- cpu register section + -- cpu read + cpu_read: process(ADDR, SPI_DATA_IN, tc, bsy, s_frx, s_pgmen, + s_ece, s_slavesel, wp, CARD, s_sdhc, s_inited) + begin + case ADDR is + when "00" => -- read SPI data in + BUS_DATA_OUT <= SPI_DATA_IN; + when "01" => -- read status register + BUS_DATA_OUT(0) <= s_pgmen; + BUS_DATA_OUT(1) <= '0'; + BUS_DATA_OUT(2) <= s_ece; + BUS_DATA_OUT(3) <= '0'; + BUS_DATA_OUT(4) <= s_frx; + BUS_DATA_OUT(5) <= BSY; + BUS_DATA_OUT(6) <= '0'; + BUS_DATA_OUT(7) <= TC; + -- "10" is unused + when "11" => -- read slave select / slave interrupt state + BUS_DATA_OUT(0) <= s_slavesel; + BUS_DATA_OUT(3 downto 1) <= (others => '0'); + BUS_DATA_OUT(4) <= s_sdhc; + BUS_DATA_OUT(5) <= WP; + BUS_DATA_OUT(6) <= CARD; + BUS_DATA_OUT(7) <= s_inited; + when others => + BUS_DATA_OUT <= (others => '0'); + end case; + end process; + + -- cpu write + cpu_write: process(NRESET, NDEV_SEL, IS_READ, ADDR, BUS_DATA_IN, CARD) + begin + if (NRESET = '0') then + s_ece <= '0'; + s_frx <= '0'; + s_slavesel <= '1'; + SPI_DATA_OUT <= (others => '1'); + s_sdhc <= '0'; + s_inited <= '0'; + s_pgmen <= '0'; + elsif (CARD = '1') then + s_sdhc <= '0'; + s_inited <= '0'; + elsif (rising_edge(NDEV_SEL) and IS_READ = '0') then + case ADDR is + when "00" => -- write SPI data out (see other process above) + SPI_DATA_OUT <= BUS_DATA_IN; + when "01" => -- write status register + s_pgmen <= BUS_DATA_IN(0); + s_ece <= BUS_DATA_IN(2); + s_frx <= BUS_DATA_IN(4); + -- no bit 5 - 7 + -- "10" is unused + when "11" => -- write slave select / slave interrupt enable + s_slavesel <= BUS_DATA_IN(0); + -- no bit 1 - 3 + s_sdhc <= BUS_DATA_IN(4); + -- no bit 5 - 6 + s_inited <= BUS_DATA_IN(7); + when others => + end case; + end if; + end process; + +end Behavioral; + diff --git a/VHDL/SpiController.vhd b/VHDL/SpiController.vhd index dca96d4..62b0d3a 100644 --- a/VHDL/SpiController.vhd +++ b/VHDL/SpiController.vhd @@ -11,26 +11,24 @@ use IEEE.STD_LOGIC_UNSIGNED.ALL; entity SpiController is Port ( - data_in : in STD_LOGIC_VECTOR (7 downto 0); - data_out : out STD_LOGIC_VECTOR (7 downto 0); - is_read : in STD_LOGIC; - nreset : in STD_LOGIC; - addr : in STD_LOGIC_VECTOR (1 downto 0); - phi0 : in STD_LOGIC; - ndev_sel : in STD_LOGIC; - clk : in STD_LOGIC; - miso: in std_logic; - mosi : out STD_LOGIC; - sclk : out STD_LOGIC; - nsel : out STD_LOGIC; - wp : in STD_LOGIC; - card : in STD_LOGIC; - pgm_en : out STD_LOGIC; - led : out STD_LOGIC + BUS_DATA : in STD_LOGIC_VECTOR (7 downto 0); + SPI_DATA : out STD_LOGIC_VECTOR (7 downto 0); + IS_READ : in STD_LOGIC; + NRESET : in STD_LOGIC; + ADDR : in STD_LOGIC_VECTOR (1 downto 0); + CLK_SLOW : in STD_LOGIC; + CLK_FAST : in STD_LOGIC; + NDEV_SEL : in STD_LOGIC; + MISO: in std_logic; + MOSI : out STD_LOGIC; + SCLK : out STD_LOGIC; + + BSY : out STD_LOGIC; + TC : out STD_LOGIC; + FRX : in std_logic; + ECE : in std_logic ); - constant DIV_WIDTH : integer := 3; - end SpiController; architecture Behavioral of SpiController is @@ -38,115 +36,109 @@ architecture Behavioral of SpiController is -------------------------- -- internal state signal spidatain: std_logic_vector (7 downto 0); - signal spidataout: std_logic_vector (7 downto 0); - signal sdhc: std_logic; -- is SDHC card - signal inited: std_logic; -- card initialized - signal pgmen: std_logic; -- enable EEPROM programming - -- spi register flags - signal tc: std_logic; -- transmission complete; cleared on spi data read - signal bsy: std_logic; -- SPI busy - signal frx: std_logic; -- fast receive mode - signal ece: std_logic; -- external clock enable; 0=phi2, 1=external clock - - signal divisor: std_logic_vector(DIV_WIDTH-1 downto 0); - signal slavesel: std_logic := '1'; -- slave select output (0=selected) - signal int_miso: std_logic; -------------------------- -- helper signals -- shift engine - signal start_shifting: std_logic := '0'; -- shifting data - signal shifting2: std_logic := '0'; -- shifting data - signal shiftdone: std_logic; -- shifting data done - signal shiftcnt: std_logic_vector(3 downto 0); -- shift counter (5 bit) + signal s_start_shifting: std_logic := '0'; -- shifting data + signal s_shifting2: std_logic := '0'; -- shifting data + signal s_shiftdone: std_logic; -- shifting data done + signal s_shiftcnt: std_logic_vector(3 downto 0); -- shift counter (5 bit) -- spi clock - signal clksrc: std_logic; -- clock source (phi2 or clk_7m) - -- TODO divcnt is not used at all?? - --signal divcnt: std_logic_vector(DIV_WIDTH-1 downto 0); -- divisor counter - signal shiftclk : std_logic; + signal s_clksrc: std_logic; -- clock source (phi2 or clk_7m) + signal s_shiftclk : std_logic; -begin - led <= not (bsy or not slavesel); - bsy <= start_shifting or shifting2; +begin + -------------------------- + -- spiclk - spi clock generation + -- spiclk is still 2 times the freq. than SCLK + s_clksrc <= CLK_SLOW when (ECE = '0') else CLK_FAST; - process(start_shifting, shiftdone, shiftclk) + -- is a pulse signal to allow for divisor==0 + s_shiftclk <= s_clksrc when (s_start_shifting or s_shifting2) = '1' else '0'; + + + BSY <= s_start_shifting or s_shifting2; + SPI_DATA <= spidatain; + + process(s_start_shifting, s_shiftdone, s_shiftclk) begin - if (rising_edge(shiftclk)) then - if (shiftdone = '1') then - shifting2 <= '0'; + if (rising_edge(s_shiftclk)) then + if (s_shiftdone = '1') then + s_shifting2 <= '0'; else - shifting2 <= start_shifting; + s_shifting2 <= s_start_shifting; end if; end if; end process; - process(shiftcnt, nreset, shiftclk) + process(s_shiftcnt, NRESET, s_shiftclk) begin - if (nreset = '0') then - shiftdone <= '0'; - elsif (rising_edge(shiftclk)) then - if (shiftcnt = "1111") then - shiftdone <= '1'; + if (NRESET = '0') then + s_shiftdone <= '0'; + elsif (rising_edge(s_shiftclk)) then + if (s_shiftcnt = "1111") then + s_shiftdone <= '1'; else - shiftdone <= '0'; + s_shiftdone <= '0'; end if; end if; end process; - process(nreset, shifting2, shiftcnt, shiftclk) + process(NRESET, s_shifting2, s_shiftcnt, s_shiftclk) begin - if (nreset = '0') then - shiftcnt <= (others => '0'); - elsif (rising_edge(shiftclk)) then - if (shifting2 = '1') then + if (NRESET = '0') then + s_shiftcnt <= (others => '0'); + elsif (rising_edge(s_shiftclk)) then + if (s_shifting2 = '1') then -- count phase - shiftcnt <= shiftcnt + 1; + s_shiftcnt <= s_shiftcnt + 1; else - shiftcnt <= (others => '0'); + s_shiftcnt <= (others => '0'); end if; end if; end process; - inproc: process(nreset, shifting2, shiftcnt, shiftclk, spidatain, miso) + inproc: process(NRESET, s_shifting2, s_shiftcnt, s_shiftclk, spidatain, miso) begin - if (nreset = '0') then + if (NRESET = '0') then spidatain <= (others => '0'); - elsif (rising_edge(shiftclk)) then - if (shifting2 = '1' and shiftcnt(0) = '1') then + elsif (rising_edge(s_shiftclk)) then + if (s_shifting2 = '1' and s_shiftcnt(0) = '1') then -- shift in to input register spidatain (7 downto 1) <= spidatain (6 downto 0); - spidatain (0) <= int_miso; + spidatain (0) <= MISO; end if; end if; end process; - outproc: process(nreset, shifting2, spidataout, shiftcnt, shiftclk) + outproc: process(NRESET, s_shifting2, BUS_DATA, s_shiftcnt, s_shiftclk) begin - if (nreset = '0') then - mosi <= '1'; - sclk <= '1'; + if (NRESET = '0') then + MOSI <= '1'; + SCLK <= '1'; else -- clock is sync'd - if (rising_edge(shiftclk)) then - if (shifting2='0' or shiftdone = '1') then - mosi <= '1'; - sclk <= '1'; + if (rising_edge(s_shiftclk)) then + if (s_shifting2='0' or s_shiftdone = '1') then + MOSI <= '1'; + SCLK <= '1'; else -- output data directly from output register - case shiftcnt(3 downto 1) is - when "000" => mosi <= spidataout(7); - when "001" => mosi <= spidataout(6); - when "010" => mosi <= spidataout(5); - when "011" => mosi <= spidataout(4); - when "100" => mosi <= spidataout(3); - when "101" => mosi <= spidataout(2); - when "110" => mosi <= spidataout(1); - when "111" => mosi <= spidataout(0); - when others => mosi <= '1'; + case s_shiftcnt(3 downto 1) is + when "000" => MOSI <= BUS_DATA(7); + when "001" => MOSI <= BUS_DATA(6); + when "010" => MOSI <= BUS_DATA(5); + when "011" => MOSI <= BUS_DATA(4); + when "100" => MOSI <= BUS_DATA(3); + when "101" => MOSI <= BUS_DATA(2); + when "110" => MOSI <= BUS_DATA(1); + when "111" => MOSI <= BUS_DATA(0); + when others => MOSI <= '1'; end case; - sclk <= shiftcnt(0); + SCLK <= s_shiftcnt(0); end if; end if; end if; @@ -154,125 +146,24 @@ begin -- shift operation enable - shiften: process(nreset, ndev_sel, is_read, addr, frx, shiftdone) + shiften: process(NRESET, NDEV_SEL, IS_READ, ADDR, FRX, s_shiftdone) begin -- start shifting - if (nreset = '0' or shiftdone = '1') then - start_shifting <= '0'; - elsif (rising_edge(ndev_sel) and addr="00" and (frx='1' or is_read='0')) then - -- access to register 00, either write (is_read=0) or fast receive bit set (frx) + if (NRESET = '0' or s_shiftdone = '1') then + s_start_shifting <= '0'; + elsif (rising_edge(NDEV_SEL) and ADDR="00" and (FRX='1' or IS_READ='0')) then + -- access to register 00, either write (IS_READ=0) or fast receive bit set (frx) -- then both types of access (write but also read) - start_shifting <= '1'; - end if; - end process; - - -------------------------- - -- spiclk - spi clock generation - -- spiclk is still 2 times the freq. than sclk - clksrc <= phi0 when (ece = '0') else clk; - - -- is a pulse signal to allow for divisor==0 - --shiftclk <= clksrc when divcnt = "000000" else '0'; - shiftclk <= clksrc when bsy = '1' else '0'; - --- clkgen: process(nreset, divisor, clksrc) --- begin --- if (nreset = '0') then --- divcnt <= divisor; --- elsif (falling_edge(clksrc)) then --- if (shiftclk = '1') then --- divcnt <= divisor; --- else --- divcnt <= divcnt - 1; --- end if; --- end if; --- end process; - - -------------------------- - -- interface section - -- inputs - int_miso <= (miso and not slavesel); - - -- outputs - nsel <= slavesel; - pgm_en <= pgmen; - - tc_proc: process (ndev_sel, shiftdone) - begin - if (shiftdone = '1') then - tc <= '1'; - elsif (rising_edge(ndev_sel) and addr="00") then - tc <= '0'; + s_start_shifting <= '1'; end if; end process; - -------------------------- - -- cpu register section - -- cpu read - cpu_read: process(addr, spidatain, tc, bsy, frx, pgmen, - ece, divisor, slavesel, wp, card, sdhc, inited) + tc_proc: process (NDEV_SEL, s_shiftdone) begin - case addr is - when "00" => -- read SPI data in - data_out <= spidatain; - when "01" => -- read status register - data_out(0) <= pgmen; - data_out(1) <= '0'; - data_out(2) <= ece; - data_out(3) <= '0'; - data_out(4) <= frx; - data_out(5) <= bsy; - data_out(6) <= '0'; - data_out(7) <= tc; - when "10" => -- read sclk divisor - data_out(DIV_WIDTH-1 downto 0) <= divisor; - data_out(7 downto 3) <= (others => '0'); - when "11" => -- read slave select / slave interrupt state - data_out(0) <= slavesel; - data_out(3 downto 1) <= (others => '0'); - data_out(4) <= sdhc; - data_out(5) <= wp; - data_out(6) <= card; - data_out(7) <= inited; - when others => - data_out <= (others => '0'); - end case; - end process; - - -- cpu write - cpu_write: process(nreset, ndev_sel, is_read, addr, data_in, card) - begin - if (nreset = '0') then - ece <= '0'; - frx <= '0'; - slavesel <= '1'; - divisor <= (others => '0'); - spidataout <= (others => '1'); - sdhc <= '0'; - inited <= '0'; - pgmen <= '0'; - elsif (card = '1') then - sdhc <= '0'; - inited <= '0'; - elsif (rising_edge(ndev_sel) and is_read = '0') then - case addr is - when "00" => -- write SPI data out (see other process above) - spidataout <= data_in; - when "01" => -- write status register - pgmen <= data_in(0); - ece <= data_in(2); - frx <= data_in(4); - -- no bit 5 - 7 - when "10" => -- write divisor - divisor <= data_in(DIV_WIDTH-1 downto 0); - when "11" => -- write slave select / slave interrupt enable - slavesel <= data_in(0); - -- no bit 1 - 3 - sdhc <= data_in(4); - -- no bit 5 - 6 - inited <= data_in(7); - when others => - end case; + if (s_shiftdone = '1') then + TC <= '1'; + elsif (rising_edge(NDEV_SEL) and ADDR="00") then + TC <= '0'; end if; end process;