Revision 215
Added by markw about 11 years ago
| mist/data_io.vhdl | ||
|---|---|---|
| 
     LIBRARY ieee;
 
   | 
||
| 
     USE ieee.std_logic_1164.all; 
 
   | 
||
| 
     use ieee.numeric_std.all;
 
   | 
||
| 
     | 
||
| 
     LIBRARY work;
 
   | 
||
| 
     | 
||
| 
     ENTITY data_io IS 
 
   | 
||
| 
     	PORT
 
   | 
||
| 
     	(
 
   | 
||
| 
     		CLK : in std_logic;
 
   | 
||
| 
     		RESET_n : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- SPI connection - up to upstream to make miso 'Z' on ss_io going high
 
   | 
||
| 
     	   SPI_CLK : in std_logic;
 
   | 
||
| 
     	   SPI_SS_IO : in std_logic;
 
   | 
||
| 
     	   SPI_MISO: out std_logic;
 
   | 
||
| 
     	   SPI_MOSI : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- Sector access read_request
 
   | 
||
| 
     		read_request : in std_logic;
 
   | 
||
| 
     		write_request : in std_logic;
 
   | 
||
| 
     		sector : in std_logic_vector(25 downto 0);
 
   | 
||
| 
     		ready : out std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- DMA to RAM
 
   | 
||
| 
     		ADDR: out std_logic_vector(8 downto 0);
 
   | 
||
| 
     		DATA_OUT : out std_logic_vector(7 downto 0);
 
   | 
||
| 
     		DATA_IN : in std_logic_vector(7 downto 0);
 
   | 
||
| 
     		WR_EN : out std_logic
 
   | 
||
| 
     	 );
 
   | 
||
| 
     end data_io;
 
   | 
||
| 
     | 
||
| 
     architecture vhdl of data_io is
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
        signal sbuf_next : std_logic_vector(6 downto 0);
 
   | 
||
| 
     	signal sbuf_reg : std_logic_vector(6 downto 0);
 
   | 
||
| 
     | 
||
| 
        signal cmd_next : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal cmd_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal cnt_next : std_logic_vector(15 downto 0);
 
   | 
||
| 
     	signal cnt_reg : std_logic_vector(15 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal data_in_next : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal data_in_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal data_out_next : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal data_out_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal addr_next : std_logic_vector(8 downto 0);
 
   | 
||
| 
     	signal addr_reg : std_logic_vector(8 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal wren_next : std_logic;
 
   | 
||
| 
     	signal wren_reg : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal ready_next : std_logic;
 
   | 
||
| 
     	signal ready_reg : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal transmit_next : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal transmit_reg : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal sector_next : std_logic_vector(25 downto 0);
 
   | 
||
| 
     	signal sector_reg : std_logic_vector(25 downto 0);
 
   | 
||
| 
     | 
||
| 
     	signal read_request_next : std_logic;
 
   | 
||
| 
     	signal read_request_reg : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal write_request_next : std_logic;
 
   | 
||
| 
     	signal write_request_reg : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal clk2 : std_logic;
 
   | 
||
| 
     begin	 
 
   | 
||
| 
     	clk2 <= clk or spi_ss_io;
 
   | 
||
| 
     | 
||
| 
     	process(clk2,reset_n,spi_ss_io)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		if (spi_ss_io = '1') then
 
   | 
||
| 
     			cnt_reg <= (others=>'0');
 
   | 
||
| 
     			cmd_reg <= (others=>'0');
 
   | 
||
| 
     			wren_reg <= '0';
 
   | 
||
| 
     		elsif (reset_n = '0') then
 
   | 
||
| 
     			cnt_reg <= (others=>'0');
 
   | 
||
| 
     			cmd_reg <= (others=>'0');
 
   | 
||
| 
     			sbuf_reg <= (others=>'0');
 
   | 
||
| 
     | 
||
| 
     			addr_reg <= (others => '0');
 
   | 
||
| 
     			data_in_reg <= (others => '0');
 
   | 
||
| 
     			data_out_reg <= (others => '0');
 
   | 
||
| 
     			wren_reg <= '0';			
 
   | 
||
| 
     | 
||
| 
     			ready_reg <= '0';
 
   | 
||
| 
     | 
||
| 
     			transmit_reg <= (others=>'0');
 
   | 
||
| 
     | 
||
| 
     			read_request_reg <= '0';
 
   | 
||
| 
     			write_request_reg <= '0';
 
   | 
||
| 
     			sector_reg <=(others=>'0');
 
   | 
||
| 
     		elsif (clk2'event and clk2='1') then
 
   | 
||
| 
     			cnt_reg <= cnt_next;
 
   | 
||
| 
     			cmd_reg <= cmd_next;
 
   | 
||
| 
     			sbuf_reg <= sbuf_next;			
 
   | 
||
| 
     | 
||
| 
     			addr_reg <= addr_next;
 
   | 
||
| 
     			data_in_reg <= data_in_next;
 
   | 
||
| 
     			data_out_reg <= data_out_next;
 
   | 
||
| 
     			wren_reg <= wren_next;
 
   | 
||
| 
     | 
||
| 
     			ready_reg <= ready_next;
 
   | 
||
| 
     | 
||
| 
     			transmit_reg <= transmit_next;
 
   | 
||
| 
     | 
||
| 
     			read_request_reg <= read_request_next;
 
   | 
||
| 
     			write_request_reg <= write_request_next;
 
   | 
||
| 
     			sector_reg <= sector_next;			
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     	end process;	
 
   | 
||
| 
     | 
||
| 
     --	clk_sync : synchronizer
 
   | 
||
| 
     --	PORT MAP ( CLK => clk, raw => spi_clk, sync=>spi_clk_next);
 
   | 
||
| 
     --spi_clk_next <= spi_clk;
 
   | 
||
| 
     | 
||
| 
     --	input_sync : synchronizer
 
   | 
||
| 
     --	PORT MAP ( CLK => clk, raw => spi_mosi, sync=>spi_mosi_next);
 
   | 
||
| 
     | 
||
| 
     --	select_sync : synchronizer
 
   | 
||
| 
     --	PORT MAP ( CLK => clk, raw => spi_ss_io, sync=>spi_ss_next);
 
   | 
||
| 
     | 
||
| 
     	data_in_next <= data_in;
 
   | 
||
| 
     | 
||
| 
     	process(spi_ss_io,cnt_reg, sbuf_reg, transmit_reg, spi_mosi, addr_reg, cmd_reg, sector_reg, write_request_reg, read_request_reg, ready_reg,read_request,write_request,sector,data_in_reg)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		cnt_next <= cnt_reg;
 
   | 
||
| 
     		sbuf_next <= sbuf_reg;
 
   | 
||
| 
     		cmd_next <= cmd_reg;
 
   | 
||
| 
     		ready_next <= ready_reg and (read_request or write_request); -- stay ready until read_request cleared (received by other end)
 
   | 
||
| 
     | 
||
| 
     		transmit_next <= transmit_reg;
 
   | 
||
| 
     | 
||
| 
     		wren_next <= '0';
 
   | 
||
| 
     		data_out_next <= (others=>'0');		
 
   | 
||
| 
     		addr_next <= addr_reg;
 
   | 
||
| 
     | 
||
| 
     		sector_next <= sector_reg;
 
   | 
||
| 
     		read_request_next <= read_request_reg;		
 
   | 
||
| 
     		write_request_next <= write_request_reg;		
 
   | 
||
| 
     | 
||
| 
     --- It polls get_status 10 times a second
 
   | 
||
| 
     --- it uses SPI_SS2 for this
 
   | 
||
| 
     --- it sends command code 0x50
 
   | 
||
| 
     --- reads 4 bytes afterwards
 
   | 
||
| 
     | 
||
| 
     --- it reports whenever the returned value is different then the one from previous get_status
 
   | 
||
| 
     | 
||
| 
     --- if the lowest byte of the status (the last transmitted of the four) is 0xa5:
 
   | 
||
| 
     --- a sector is read from sd card with the sector no being the upper/first three bytes transmitted
 
   | 
||
| 
     --- if the sector could be read
 
   | 
||
| 
     --- SPI_SS2 is activated
 
   | 
||
| 
     --- command byte 0x51 is sent
 
   | 
||
| 
     --- all 512 sector bytes are sent
 
   | 
||
| 
     | 
||
| 
     		--if (spi_clk_reg = '1' and spi_clk_next = '0') then
 
   | 
||
| 
     		transmit_next(7 downto 1) <= transmit_reg(6 downto 0);
 
   | 
||
| 
     		transmit_next(0) <= '0';
 
   | 
||
| 
     | 
||
| 
     		cnt_next <= std_logic_vector(unsigned(cnt_reg) + 1);		
 
   | 
||
| 
     | 
||
| 
     		sbuf_next(6 downto 1) <= sbuf_reg(5 downto 0);
 
   | 
||
| 
     		sbuf_next(0) <= SPI_MOSI;
 
   | 
||
| 
     | 
||
| 
     		if (cnt_reg = X"0000") then
 
   | 
||
| 
     			addr_next <= (others=>'0');
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		if (cnt_reg = X"0007") then
 
   | 
||
| 
     			cmd_next(7 downto 1) <= sbuf_reg;
 
   | 
||
| 
     			cmd_next(0) <= SPI_MOSI;
 
   | 
||
| 
     | 
||
| 
     			sector_next <= sector;
 
   | 
||
| 
     			read_request_next <= read_request;		
 
   | 
||
| 
     			write_request_next <= write_request;		
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| 
     		--end if;
 
   | 
||
| 
     | 
||
| 
     		case cmd_reg is
 
   | 
||
| 
     		when X"50" => --get status
 
   | 
||
| 
     			case cnt_reg is 
 
   | 
||
| 
     			when X"0008" =>
 
   | 
||
| 
     				transmit_next <= sector_reg(25 downto 18);
 
   | 
||
| 
     			when X"0010" =>
 
   | 
||
| 
     				transmit_next <= sector_reg(17 downto 10);
 
   | 
||
| 
     			when X"0018" =>
 
   | 
||
| 
     				transmit_next <= sector_reg(9 downto 2);				
 
   | 
||
| 
     			when X"0020" =>
 
   | 
||
| 
     				transmit_next <= sector_reg(1 downto 0)&"1010"&write_request_reg&read_request_reg; --read read_request
 
   | 
||
| 
     			when others =>
 
   | 
||
| 
     				-- nothing
 
   | 
||
| 
     			end case;
 
   | 
||
| 
     		when X"51" => --sector read from sd, write it...
 
   | 
||
| 
     			if (cnt_reg = X"0008") then
 
   | 
||
| 
     				addr_next <= (others=>'1');
 
   | 
||
| 
     			end if;
 
   | 
||
| 
     			if (cnt_reg(2 downto 0) = "111") then
 
   | 
||
| 
     				addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
 
   | 
||
| 
     				data_out_next(7 downto 1) <= sbuf_reg;
 
   | 
||
| 
     				data_out_next(0) <= SPI_MOSI;
 
   | 
||
| 
     				wren_next <= read_request;
 
   | 
||
| 
     | 
||
| 
     				if (cnt_reg(12) = '1')then
 
   | 
||
| 
     					ready_next <= '1';
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			end if;
 
   | 
||
| 
     		when X"52" => -- read from write, write to sd
 
   | 
||
| 
     			if (cnt_reg(2 downto 0) = "000") then
 
   | 
||
| 
     				addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
 
   | 
||
| 
     				transmit_next <= data_in_reg;
 
   | 
||
| 
     | 
||
| 
     				if (cnt_reg(12) = '1')then
 
   | 
||
| 
     					ready_next <= '1';
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			end if;
 
   | 
||
| 
     		when others =>
 
   | 
||
| 
     			-- nop
 
   | 
||
| 
     		end case;
 
   | 
||
| 
     	end process;
 
   | 
||
| 
     | 
||
| 
     	-- outputs
 
   | 
||
| 
     	addr <= addr_next;
 
   | 
||
| 
     	data_out <= data_out_next;
 
   | 
||
| 
     	wr_en <= wren_next;
 
   | 
||
| 
     | 
||
| 
     	ready <= ready_reg;
 
   | 
||
| 
     | 
||
| 
     	spi_miso <= transmit_next(7);
 
   | 
||
| 
     end vhdl;
 
   | 
||
| firmware/Makefile | ||
|---|---|---|
| 
     MCC_OBJ = $(patsubst %.c,$(MCC_BUILD_DIR)/%.o,$(MCC_SRC))
 
   | 
||
| 
     | 
||
| 
     MIST_PRJ = MIST
 
   | 
||
| 
     MIST_SRC = $(COMMON_SRC) $(A800_SRC) mist/diskio_sectorrequest.c mist/dirs.c
 
   | 
||
| 
     MIST_SRC = $(COMMON_SRC) $(SDCARD_SRC) $(A800_SRC) mist/dirs.c
 
   | 
||
| 
     MIST_OBJ = $(patsubst %.c,$(MIST_BUILD_DIR)/%.o,$(MIST_SRC))
 
   | 
||
| 
     | 
||
| 
     MIST_5200_PRJ = MIST_5200
 
   | 
||
| mist/atari800core.qsf | ||
|---|---|---|
| 
     | 
||
| 
     set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
 
   | 
||
| 
     | 
||
| 
     set_global_assignment -name VHDL_FILE data_io.vhdl
 
   | 
||
| 
     set_global_assignment -name VHDL_FILE zpu_rom.vhdl
 
   | 
||
| 
     set_global_assignment -name SDC_FILE atari800core.sdc
 
   | 
||
| 
     set_global_assignment -name QIP_FILE mist_sector_buffer.qip
 
   | 
||
| 
     set_global_assignment -name VHDL_FILE atari800core_mist.vhd
 
   | 
||
| 
     set_global_assignment -name VERILOG_FILE user_io.v
 
   | 
||
| 
     set_global_assignment -name VERILOG_FILE sd_card.v
 
   | 
||
| 
     set_global_assignment -name QIP_FILE pll_pal_pre.qip
 
   | 
||
| 
     set_global_assignment -name QIP_FILE pll_pal_post.qip
 
   | 
||
| 
     set_global_assignment -name QIP_FILE pll_ntsc.qip
 
   | 
||
| mist/atari800core_mist.vhd | ||
|---|---|---|
| 
     end component;
 
   | 
||
| 
     | 
||
| 
     component user_io
 
   | 
||
| 
     	GENERIC(
 
   | 
||
| 
     		STRLEN : in integer := 0
 
   | 
||
| 
     	);
 
   | 
||
| 
     	PORT(
 
   | 
||
| 
     	   SPI_CLK : in std_logic;
 
   | 
||
| 
     	   SPI_SS_IO : in std_logic;
 
   | 
||
| 
     	   SPI_MISO : out std_logic;
 
   | 
||
| 
     	   SPI_MOSI : in std_logic;
 
   | 
||
| 
     	   CORE_TYPE : in std_logic_vector(7 downto 0);
 
   | 
||
| 
     		JOY0 : out std_logic_vector(5 downto 0);
 
   | 
||
| 
     		JOY1 : out std_logic_vector(5 downto 0);
 
   | 
||
| 
     		-- conf_str? how to do in vhdl...
 
   | 
||
| 
     | 
||
| 
     		-- mist spi to firmware
 
   | 
||
| 
     		SPI_CLK : in std_logic;
 
   | 
||
| 
     		SPI_SS_IO : in std_logic;
 
   | 
||
| 
     		SPI_MISO : out std_logic;
 
   | 
||
| 
     		SPI_MOSI : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- joysticks
 
   | 
||
| 
     		JOYSTICK_0 : out std_logic_vector(5 downto 0);
 
   | 
||
| 
     		JOYSTICK_1 : out std_logic_vector(5 downto 0);
 
   | 
||
| 
     		JOYSTICK_ANALOG_0 : out std_logic_vector(15 downto 0);
 
   | 
||
| 
     		JOYSTICK_ANALOG_1 : out std_logic_vector(15 downto 0);
 
   | 
||
| 
     		BUTTONS : out std_logic_vector(1 downto 0);
 
   | 
||
| 
     		SWITCHES : out std_logic_vector(1 downto 0);
 
   | 
||
| 
     		CLK : in std_logic;
 
   | 
||
| 
     		PS2_CLK : out std_logic;
 
   | 
||
| 
     		PS2_DATA : out std_logic
 
   | 
||
| 
     		STATUS : out std_logic_vector(7 downto 0); -- what is this?
 
   | 
||
| 
     | 
||
| 
     		-- ps2
 
   | 
||
| 
     		PS2_CLK : in std_logic; --12-16khz
 
   | 
||
| 
     		PS2_KBD_CLK : out std_logic;
 
   | 
||
| 
     		PS2_KBD_DATA : out std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- serial (one way?)
 
   | 
||
| 
     		SERIAL_DATA : in std_logic_vector(7 downto 0);
 
   | 
||
| 
     		SERIAL_STROBE : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- connection to sd card emulation
 
   | 
||
| 
     		sd_lba : in std_logic_vector(31 downto 0);
 
   | 
||
| 
     		sd_rd : in std_logic;
 
   | 
||
| 
     		sd_wr : in std_logic;
 
   | 
||
| 
     		sd_ack : out std_logic;
 
   | 
||
| 
     		sd_conf : in std_logic;
 
   | 
||
| 
     		sd_sdhc : in std_logic;
 
   | 
||
| 
     		sd_dout : out std_logic_vector(7 downto 0);
 
   | 
||
| 
     		sd_dout_strobe : out std_logic;
 
   | 
||
| 
     		sd_din : in std_logic_vector(7 downto 0);
 
   | 
||
| 
     		sd_din_strobe : out std_logic
 
   | 
||
| 
     	  );
 
   | 
||
| 
     end component;
 
   | 
||
| 
     	end component;
 
   | 
||
| 
     | 
||
| 
     	component sd_card
 
   | 
||
| 
     	PORT (
 
   | 
||
| 
     		-- link to user_io for io controller
 
   | 
||
| 
     		io_lba : out std_logic_vector(31 downto 0);
 
   | 
||
| 
     		io_rd : out std_logic;
 
   | 
||
| 
     		io_wr : out std_logic;
 
   | 
||
| 
     		io_ack : in std_logic;
 
   | 
||
| 
     		io_conf : out std_logic;
 
   | 
||
| 
     		io_sdhc : out std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- data coming in from io controller
 
   | 
||
| 
     		io_din : in std_logic_vector(7 downto 0);
 
   | 
||
| 
     		io_din_strobe : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- data going out to io controller
 
   | 
||
| 
     		io_dout : out std_logic_vector(7 downto 0);
 
   | 
||
| 
     		io_dout_strobe : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		-- configuration input
 
   | 
||
| 
     		allow_sdhc : in std_logic;
 
   | 
||
| 
     | 
||
| 
     		sd_cs : in std_logic;
 
   | 
||
| 
     		sd_sck : in std_logic;
 
   | 
||
| 
     		sd_sdi : in std_logic;
 
   | 
||
| 
     		sd_sdo : out std_logic
 
   | 
||
| 
     	); 
 
   | 
||
| 
     	end component;
 
   | 
||
| 
     | 
||
| 
       signal AUDIO_L_PCM : std_logic_vector(15 downto 0);
 
   | 
||
| 
       signal AUDIO_R_PCM : std_logic_vector(15 downto 0);
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
       signal capsheld_next : std_logic;
 
   | 
||
| 
       signal capsheld_reg : std_logic;
 
   | 
||
| 
     | 
||
| 
       signal mist_sector_ready : std_logic;
 
   | 
||
| 
       signal mist_sector_ready_sync : std_logic;
 
   | 
||
| 
       signal mist_sector_request : std_logic;
 
   | 
||
| 
       signal mist_sector_request_sync : std_logic;
 
   | 
||
| 
       signal mist_sector_write : std_logic;
 
   | 
||
| 
       signal mist_sector_write_sync : std_logic;
 
   | 
||
| 
       signal mist_sector : std_logic_vector(25 downto 0);
 
   | 
||
| 
       signal mist_sector_sync : std_logic_vector(25 downto 0);
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
       signal mist_addr : std_logic_vector(8 downto 0);
 
   | 
||
| 
       signal mist_do : std_logic_vector(7 downto 0);
 
   | 
||
| 
       signal mist_di : std_logic_vector(7 downto 0);
 
   | 
||
| 
       signal mist_wren : std_logic;
 
   | 
||
| 
     | 
||
| 
       signal spi_miso_data : std_logic;
 
   | 
||
| 
       signal spi_miso_io : std_logic;
 
   | 
||
| 
     | 
||
| 
       signal mist_buttons : std_logic_vector(1 downto 0);
 
   | 
||
| ... | ... | |
| 
     	SIGNAL speed_6502 : std_logic_vector(5 downto 0);
 
   | 
||
| 
     	signal emulated_cartridge_select: std_logic_vector(5 downto 0);
 
   | 
||
| 
     | 
||
| 
     	-- mist sector
 
   | 
||
| 
     	signal ZPU_ROM_DATA_MUX :  std_logic_vector(31 downto 0);
 
   | 
||
| 
     	signal ZPU_SECTOR_DATA :  std_logic_vector(31 downto 0);
 
   | 
||
| 
     	signal ZPU_ROM_DO :  std_logic_vector(31 downto 0);
 
   | 
||
| 
     	signal ZPU_ROM_WREN :  std_logic;
 
   | 
||
| 
     	-- connection to sd card emulation
 
   | 
||
| 
     	signal sd_lba : std_logic_vector(31 downto 0);
 
   | 
||
| 
     	signal sd_rd : std_logic;
 
   | 
||
| 
     	signal sd_wr : std_logic;
 
   | 
||
| 
     	signal sd_ack : std_logic;
 
   | 
||
| 
     	signal sd_conf : std_logic;
 
   | 
||
| 
     	signal sd_sdhc : std_logic;
 
   | 
||
| 
     	signal sd_dout : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal sd_dout_strobe : std_logic;
 
   | 
||
| 
     	signal sd_din : std_logic_vector(7 downto 0);
 
   | 
||
| 
     	signal sd_din_strobe : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal mist_sd_sdo : std_logic;
 
   | 
||
| 
     	signal mist_sd_sck : std_logic;
 
   | 
||
| 
     	signal mist_sd_sdi : std_logic;
 
   | 
||
| 
     	signal mist_sd_cs : std_logic;
 
   | 
||
| 
     | 
||
| 
     	-- ps2
 
   | 
||
| 
     	signal SLOW_PS2_CLK : std_logic; -- around 16KHz
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     composite_on_hsync <= '1' when composite_sync=1 else '0';
 
   | 
||
| 
     | 
||
| 
     -- mist spi io
 
   | 
||
| 
     mist_spi_interface : entity work.data_io 
 
   | 
||
| 
     	PORT map
 
   | 
||
| 
     	(
 
   | 
||
| 
     		CLK =>spi_sck,
 
   | 
||
| 
     		RESET_n =>reset_n,
 
   | 
||
| 
     | 
||
| 
     		-- SPI connection - up to upstream to make miso 'Z' on ss_io going high
 
   | 
||
| 
     		SPI_CLK =>spi_sck,
 
   | 
||
| 
     		SPI_SS_IO => spi_ss2,
 
   | 
||
| 
     		SPI_MISO => spi_miso_data,
 
   | 
||
| 
     		SPI_MOSI => spi_di,
 
   | 
||
| 
     | 
||
| 
     		-- Sector access request
 
   | 
||
| 
     		read_request => mist_sector_request_sync,
 
   | 
||
| 
     		write_request => mist_sector_write_sync,
 
   | 
||
| 
     		--request => mist_sector_request_sync,
 
   | 
||
| 
     		sector => mist_sector_sync(25 downto 0),
 
   | 
||
| 
     		ready => mist_sector_ready,
 
   | 
||
| 
     | 
||
| 
     		-- DMA to RAM
 
   | 
||
| 
     		ADDR => mist_addr,
 
   | 
||
| 
     		DATA_OUT => mist_do,
 
   | 
||
| 
     		DATA_IN => mist_di,
 
   | 
||
| 
     		WR_EN => mist_wren
 
   | 
||
| 
     	 );
 
   | 
||
| 
     | 
||
| 
     	-- TODO, review if these are all needed when ZPU connected again...
 
   | 
||
| 
     	select_sync : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => clk, raw => mist_sector_ready, sync=>mist_sector_ready_sync);
 
   | 
||
| 
     	spi_do <= spi_miso_io when CONF_DATA0 ='0' else 'Z';
 
   | 
||
| 
     | 
||
| 
     	select_sync2 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector_request, sync=>mist_sector_request_sync);
 
   | 
||
| 
     | 
||
| 
     	select_sync3 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector_write, sync=>mist_sector_write_sync);
 
   | 
||
| 
     | 
||
| 
     	sector_sync0 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(0), sync=>mist_sector_sync(0));
 
   | 
||
| 
     | 
||
| 
     	sector_sync1 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(1), sync=>mist_sector_sync(1));
 
   | 
||
| 
     | 
||
| 
     	sector_sync2 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(2), sync=>mist_sector_sync(2));
 
   | 
||
| 
     | 
||
| 
     	sector_sync3 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(3), sync=>mist_sector_sync(3));
 
   | 
||
| 
     | 
||
| 
     	sector_sync4 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(4), sync=>mist_sector_sync(4));
 
   | 
||
| 
     | 
||
| 
     	sector_sync5 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(5), sync=>mist_sector_sync(5));
 
   | 
||
| 
     | 
||
| 
     	sector_sync6 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(6), sync=>mist_sector_sync(6));
 
   | 
||
| 
     | 
||
| 
     	sector_sync7 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(7), sync=>mist_sector_sync(7));
 
   | 
||
| 
     | 
||
| 
     	sector_sync8 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(8), sync=>mist_sector_sync(8));
 
   | 
||
| 
     | 
||
| 
     	sector_sync9 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(9), sync=>mist_sector_sync(9));
 
   | 
||
| 
     | 
||
| 
     	sector_sync10 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(10), sync=>mist_sector_sync(10));
 
   | 
||
| 
     | 
||
| 
     	sector_sync11 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(11), sync=>mist_sector_sync(11));
 
   | 
||
| 
     | 
||
| 
     	sector_sync12 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(12), sync=>mist_sector_sync(12));
 
   | 
||
| 
     | 
||
| 
     	sector_sync13 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(13), sync=>mist_sector_sync(13));
 
   | 
||
| 
     | 
||
| 
     	sector_sync14 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(14), sync=>mist_sector_sync(14));
 
   | 
||
| 
     | 
||
| 
     	sector_sync15 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(15), sync=>mist_sector_sync(15));
 
   | 
||
| 
     | 
||
| 
     	sector_sync16 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(16), sync=>mist_sector_sync(16));
 
   | 
||
| 
     | 
||
| 
     	sector_sync17 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(17), sync=>mist_sector_sync(17));
 
   | 
||
| 
     | 
||
| 
     	sector_sync18 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(18), sync=>mist_sector_sync(18));
 
   | 
||
| 
     | 
||
| 
     	sector_sync19 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(19), sync=>mist_sector_sync(19));
 
   | 
||
| 
     | 
||
| 
     	sector_sync20 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(20), sync=>mist_sector_sync(20));
 
   | 
||
| 
     | 
||
| 
     	sector_sync21 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(21), sync=>mist_sector_sync(21));
 
   | 
||
| 
     | 
||
| 
     	sector_sync22 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(22), sync=>mist_sector_sync(22));
 
   | 
||
| 
     | 
||
| 
     	sector_sync23 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(23), sync=>mist_sector_sync(23));
 
   | 
||
| 
     | 
||
| 
     	sector_sync24 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(24), sync=>mist_sector_sync(24));
 
   | 
||
| 
     | 
||
| 
     	sector_sync25 : entity work.synchronizer
 
   | 
||
| 
     	PORT MAP ( CLK => spi_sck, raw => mist_sector(25), sync=>mist_sector_sync(25));
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     	spi_do <= spi_miso_io when CONF_DATA0 ='0' else spi_miso_data when spi_SS2='0' else 'Z';
 
   | 
||
| 
     | 
||
| 
     mist_sector_buffer1 : entity work.mist_sector_buffer
 
   | 
||
| 
     	PORT map
 
   | 
||
| 
     	(
 
   | 
||
| 
     		address_a		=> mist_addr,
 
   | 
||
| 
     		address_b		=> zpu_addr_rom(8 downto 2),
 
   | 
||
| 
     		clock_a		=> spi_sck,
 
   | 
||
| 
     		clock_b		=> clk,
 
   | 
||
| 
     		data_a		=> mist_do,
 
   | 
||
| 
     		data_b		=> dma_write_data(7 downto 0)&dma_write_data(15 downto 8)&dma_write_data(23 downto 16)&dma_write_data(31 downto 24),
 
   | 
||
| 
     		wren_a		=> mist_wren,
 
   | 
||
| 
     		wren_b		=> zpu_rom_wren, 
 
   | 
||
| 
     		q_a		=> mist_di,
 
   | 
||
| 
     		q_b		=> zpu_sector_data
 
   | 
||
| 
     	);
 
   | 
||
| 
     | 
||
| 
     my_user_io : user_io
 
   | 
||
| 
     	PORT map(
 
   | 
||
| 
     	   SPI_CLK => SPI_SCK,
 
   | 
||
| 
     	   SPI_SS_IO => CONF_DATA0,
 
   | 
||
| 
     	   SPI_MISO => SPI_miso_io,
 
   | 
||
| 
     	   SPI_MOSI => SPI_DI,
 
   | 
||
| 
     	   CORE_TYPE => x"A4",
 
   | 
||
| 
     		JOY0 => joy2,
 
   | 
||
| 
     		JOY1 => joy1,
 
   | 
||
| 
     		JOYSTICK_0 => joy2,
 
   | 
||
| 
     		JOYSTICK_1 => joy1,
 
   | 
||
| 
     		JOYSTICK_ANALOG_0 => open,
 
   | 
||
| 
     		JOYSTICK_ANALOG_1 => open, -- todo, wire up to paddles
 
   | 
||
| 
     		BUTTONS => mist_buttons,
 
   | 
||
| 
     		SWITCHES => mist_switches,
 
   | 
||
| 
     		CLK => SLOW_PS2_CLK,
 
   | 
||
| 
     		PS2_CLK => ps2_clk,
 
   | 
||
| 
     		PS2_DATA => ps2_dat
 
   | 
||
| 
     		STATUS => open,
 
   | 
||
| 
     | 
||
| 
     		PS2_CLK => SLOW_PS2_CLK,
 
   | 
||
| 
     		PS2_KBD_CLK => ps2_clk,
 
   | 
||
| 
     		PS2_KBD_DATA => ps2_dat,
 
   | 
||
| 
     | 
||
| 
     		SERIAL_DATA => (others=>'0'),
 
   | 
||
| 
     		SERIAL_STROBE => '0',
 
   | 
||
| 
     | 
||
| 
     		sd_lba => sd_lba,
 
   | 
||
| 
     		sd_rd => sd_rd,
 
   | 
||
| 
     		sd_wr => sd_wr,
 
   | 
||
| 
     		sd_ack => sd_ack,
 
   | 
||
| 
     		sd_conf => sd_conf,
 
   | 
||
| 
     		sd_sdhc => sd_sdhc,
 
   | 
||
| 
     		sd_dout => sd_dout,
 
   | 
||
| 
     		sd_dout_strobe => sd_dout_strobe,
 
   | 
||
| 
     		sd_din => sd_din,
 
   | 
||
| 
     		sd_din_strobe => sd_din_strobe
 
   | 
||
| 
     	  );
 
   | 
||
| 
     | 
||
| 
     my_sd_card : sd_card
 
   | 
||
| 
     	PORT map (
 
   | 
||
| 
     		io_lba => sd_lba,
 
   | 
||
| 
     		io_rd => sd_rd,
 
   | 
||
| 
     		io_wr => sd_wr,
 
   | 
||
| 
     		io_ack => sd_ack,
 
   | 
||
| 
     		io_conf => sd_conf,
 
   | 
||
| 
     		io_sdhc => sd_sdhc,
 
   | 
||
| 
     | 
||
| 
     		io_din => sd_din,
 
   | 
||
| 
     		io_din_strobe => sd_din_strobe,
 
   | 
||
| 
     | 
||
| 
     		io_dout => sd_dout,
 
   | 
||
| 
     		io_dout_strobe => sd_dout_strobe,
 
   | 
||
| 
     | 
||
| 
     		allow_sdhc => '1',
 
   | 
||
| 
     | 
||
| 
     		sd_cs => mist_sd_cs,
 
   | 
||
| 
     		sd_sck => mist_sd_sck,
 
   | 
||
| 
     		sd_sdi => mist_sd_sdi,
 
   | 
||
| 
     		sd_sdo => mist_sd_sdo
 
   | 
||
| 
     	); 
 
   | 
||
| 
     | 
||
| 
     	 joy1_n <= not(joy1(4 downto 0));
 
   | 
||
| 
     	 joy2_n <= not(joy2(4 downto 0));
 
   | 
||
| ... | ... | |
| 
     	GENERIC MAP
 
   | 
||
| 
     	(
 
   | 
||
| 
     		platform => 1,
 
   | 
||
| 
     		spi_clock_div => 1 -- 28MHz/2. Max for SD cards is 25MHz...
 
   | 
||
| 
     		spi_clock_div => 16 -- 28MHz/2. Max for SD cards is 25MHz...
 
   | 
||
| 
     	)
 
   | 
||
| 
     	PORT MAP
 
   | 
||
| 
     	(
 
   | 
||
| ... | ... | |
| 
     		-- rom bus master
 
   | 
||
| 
     		-- data on next cycle after addr
 
   | 
||
| 
     		ZPU_ADDR_ROM => zpu_addr_rom,
 
   | 
||
| 
     		ZPU_ROM_DATA => zpu_rom_data_mux,
 
   | 
||
| 
     		ZPU_ROM_DATA => zpu_rom_data,
 
   | 
||
| 
     | 
||
| 
     		ZPU_ROM_WREN => zpu_rom_wren, -- special for mist...
 
   | 
||
| 
     		ZPU_ROM_WREN => open,
 
   | 
||
| 
     | 
||
| 
     		-- spi master
 
   | 
||
| 
     		-- not used for mist...
 
   | 
||
| 
     		ZPU_SD_DAT0 => '0',
 
   | 
||
| 
     		ZPU_SD_CLK => open,
 
   | 
||
| 
     		ZPU_SD_CMD => open,
 
   | 
||
| 
     		ZPU_SD_DAT3 => open,
 
   | 
||
| 
     		ZPU_SD_DAT0 => mist_sd_sdo,
 
   | 
||
| 
     		ZPU_SD_CLK => mist_sd_sck,
 
   | 
||
| 
     		ZPU_SD_CMD => mist_sd_sdi,
 
   | 
||
| 
     		ZPU_SD_DAT3 => mist_sd_cs,
 
   | 
||
| 
     | 
||
| 
     		-- SIO
 
   | 
||
| 
     		-- Ditto for speaking to Atari, we have a built in Pokey
 
   | 
||
| ... | ... | |
| 
     		ZPU_IN1 => X"00000"&(FKEYS(11) or (mist_buttons(0) and not(joy1_n(4))))&(FKEYS(10) or (mist_buttons(0) and joy1_n(4) and joy_still))&(FKEYS(9) or (mist_buttons(0) and joy1_n(4) and not(joy_still)))&FKEYS(8 downto 0),
 
   | 
||
| 
     		ZPU_IN2 => X"00000000",
 
   | 
||
| 
     		ZPU_IN3 => X"00000000",
 
   | 
||
| 
     		ZPU_IN4 => X"000000"&"0000000"&mist_sector_ready_sync,
 
   | 
||
| 
     		ZPU_IN4 => X"00000000",
 
   | 
||
| 
     | 
||
| 
     		-- ouputs - e.g. Atari system control, halt, throttle, rom select
 
   | 
||
| 
     		ZPU_OUT1 => zpu_out1,
 
   | 
||
| ... | ... | |
| 
     		ZPU_OUT4 => zpu_out4
 
   | 
||
| 
     	);
 
   | 
||
| 
     | 
||
| 
     	mist_sector <= zpu_out4(25 downto 0);
 
   | 
||
| 
     	mist_sector_request <= zpu_out4(26);
 
   | 
||
| 
     	mist_sector_write <= zpu_out4(27);
 
   | 
||
| 
     | 
||
| 
     	pause_atari <= zpu_out1(0);
 
   | 
||
| 
     	reset_atari <= zpu_out1(1);
 
   | 
||
| 
     	speed_6502 <= zpu_out1(7 downto 2);
 
   | 
||
| ... | ... | |
| 
     	        q => zpu_rom_data
 
   | 
||
| 
     	);
 
   | 
||
| 
     | 
||
| 
     process(zpu_addr_rom, zpu_rom_data, zpu_sector_data)
 
   | 
||
| 
     begin
 
   | 
||
| 
     	zpu_rom_data_mux <= zpu_rom_data;
 
   | 
||
| 
     	if (zpu_addr_rom(15 downto 14) = "01") then
 
   | 
||
| 
     		zpu_rom_data_mux <= zpu_sector_data(7 downto 0)&zpu_sector_data(15 downto 8)&zpu_sector_data(23 downto 16)&zpu_sector_data(31 downto 24);
 
   | 
||
| 
     	end if;
 
   | 
||
| 
     end process;
 
   | 
||
| 
     | 
||
| 
     enable_179_clock_div_zpu_pokey : entity work.enable_divider
 
   | 
||
| 
     	generic map (COUNT=>32) -- cycle_length
 
   | 
||
| 
     	port map(clk=>clk,reset_n=>reset_n,enable_in=>'1',enable_out=>zpu_pokey_enable);
 
   | 
||
| mist/sd_card.v | ||
|---|---|---|
| 
     // 
 
   | 
||
| 
     // sd_card.v
 
   | 
||
| 
     //
 
   | 
||
| 
     // This file implelents a sd card for the MIST board since on the board
 
   | 
||
| 
     // the SD card is connected to the ARM IO controller and the FPGA has no
 
   | 
||
| 
     // direct connection to the SD card. This file provides a SD card like
 
   | 
||
| 
     // interface to the IO controller easing porting of cores that expect
 
   | 
||
| 
     // a direct interface to the SD card.
 
   | 
||
| 
     //
 
   | 
||
| 
     // Copyright (c) 2014 Till Harbaum <till@harbaum.org>
 
   | 
||
| 
     //
 
   | 
||
| 
     // 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 <http://www.gnu.org/licenses/>.
 
   | 
||
| 
     //
 
   | 
||
| 
     // http://elm-chan.org/docs/mmc/mmc_e.html
 
   | 
||
| 
     | 
||
| 
     // TODO:
 
   | 
||
| 
     // - CMD9: SEND_CSD (requires device capacity)
 
   | 
||
| 
     // - CMD10: SEND_CID
 
   | 
||
| 
     | 
||
| 
     module sd_card (
 
   | 
||
| 
     	// link to user_io for io controller
 
   | 
||
| 
     	output [31:0] io_lba,
 
   | 
||
| 
     	output reg    io_rd,
 
   | 
||
| 
     	output reg    io_wr,
 
   | 
||
| 
     	input			  io_ack,
 
   | 
||
| 
     	output		  io_conf,
 
   | 
||
| 
     	output		  io_sdhc,
 
   | 
||
| 
     | 
||
| 
     	// data coming in from io controller
 
   | 
||
| 
     	input	[7:0]	  io_din,
 
   | 
||
| 
     	input 		  io_din_strobe,
 
   | 
||
| 
     | 
||
| 
     	// data going out to io controller
 
   | 
||
| 
     	output [7:0]  io_dout,
 
   | 
||
| 
     	input 		  io_dout_strobe,
 
   | 
||
| 
     | 
||
| 
     	// configuration input
 
   | 
||
| 
     	input         allow_sdhc,
 
   | 
||
| 
     | 
||
| 
        input         sd_cs,
 
   | 
||
| 
        input         sd_sck,
 
   | 
||
| 
        input         sd_sdi,
 
   | 
||
| 
        output reg    sd_sdo
 
   | 
||
| 
     ); 
 
   | 
||
| 
     | 
||
| 
     // set io_rd once read_state machine starts waiting (rising edge of req_io_rd)
 
   | 
||
| 
     // and clear it once io controller uploads something (io_ack==1) 
 
   | 
||
| 
     wire req_io_rd = (read_state == 3'd1);
 
   | 
||
| 
     wire io_reset = io_ack || sd_cs;
 
   | 
||
| 
     always @(posedge req_io_rd or posedge io_reset) begin
 
   | 
||
| 
     	if(io_reset) io_rd <= 1'b0;
 
   | 
||
| 
     	else 		    io_rd <= 1'b1;
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     wire req_io_wr = (write_state == 3'd6);
 
   | 
||
| 
     always @(posedge req_io_wr or posedge io_reset) begin
 
   | 
||
| 
     	if(io_reset) io_wr <= 1'b0;
 
   | 
||
| 
     	else 		    io_wr <= 1'b1;
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     wire [31:0] OCR = { 1'b0, io_sdhc, 30'h0 };  // bit30 = 1 -> high capaciry card (sdhc)
 
   | 
||
| 
     wire [7:0] READ_DATA_TOKEN = 8'hfe;
 
   | 
||
| 
     | 
||
| 
     localparam NCR=4;
 
   | 
||
| 
     | 
||
| 
     // 0=idle, 1=wait for io ctrl, 2=wait for byte start, 2=send token, 3=send data, 4/5=send crc[0..1]
 
   | 
||
| 
     reg [2:0] read_state;  
 
   | 
||
| 
     | 
||
| 
     // 0=idle
 
   | 
||
| 
     reg [2:0] write_state;  
 
   | 
||
| 
     | 
||
| 
     reg [6:0] sbuf; 
 
   | 
||
| 
     reg cmd55;
 
   | 
||
| 
     reg [7:0] cmd;
 
   | 
||
| 
     reg [2:0] bit_cnt;    // counts bits 0-7 0-7 ...
 
   | 
||
| 
     reg [7:0] byte_cnt;   // counts bytes
 
   | 
||
| 
     reg [7:0] cmd_cnt;    // counts command bytes
 
   | 
||
| 
     | 
||
| 
     reg [7:0] lba0, lba1, lba2, lba3;
 
   | 
||
| 
     assign io_lba = io_sdhc?{ lba3, lba2, lba1, lba0 }:{9'd0, lba3, lba2, lba1[7:1]};
 
   | 
||
| 
     | 
||
| 
     // the command crc is actually never evaluated
 
   | 
||
| 
     reg [7:0] crc;
 
   | 
||
| 
     | 
||
| 
     reg [7:0] reply;
 
   | 
||
| 
     reg [7:0] reply0, reply1, reply2, reply3;
 
   | 
||
| 
     reg [3:0] reply_len;
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     reg io_ackD, io_ackD2;
 
   | 
||
| 
     | 
||
| 
     // signals to address buffer on SD card write (data coming from SD spi)
 
   | 
||
| 
     reg write_strobe;
 
   | 
||
| 
     reg [7:0] write_data;
 
   | 
||
| 
     | 
||
| 
     // ------------------------- SECTOR BUFFER -----------------------
 
   | 
||
| 
     | 
||
| 
     // access to the sector buffer is multiplexed. When reading sectors 
 
   | 
||
| 
     // the io controller writes into the buffer and the sd card implementation
 
   | 
||
| 
     // reads. And vice versa when writing sectors
 
   | 
||
| 
     wire reading = (read_state != 0);
 
   | 
||
| 
     wire writing = (write_state != 0);
 
   | 
||
| 
     | 
||
| 
     // the buffer itself. Can hold one sector
 
   | 
||
| 
     reg [8:0] buffer_wptr;
 
   | 
||
| 
     reg [8:0] buffer_rptr;
 
   | 
||
| 
     reg [7:0] buffer [511:0];
 
   | 
||
| 
     reg [7:0] buffer_byte;
 
   | 
||
| 
     | 
||
| 
     // ---------------- buffer read engine -----------------------
 
   | 
||
| 
     reg core_buffer_read_strobe;
 
   | 
||
| 
     wire buffer_read_latch = reading?sd_sck:io_dout_strobe;
 
   | 
||
| 
     wire buffer_read_strobe = reading?core_buffer_read_strobe:!io_dout_strobe;
 
   | 
||
| 
     assign io_dout = buffer_byte;
 
   | 
||
| 
     | 
||
| 
     // sdo is sampled on negative sd clock so set it on positive edge
 
   | 
||
| 
     always @(posedge buffer_read_latch)
 
   | 
||
| 
     	buffer_byte <= buffer[buffer_rptr];
 
   | 
||
| 
     | 
||
| 
     always @(posedge buffer_read_strobe or posedge sd_cs) begin
 
   | 
||
| 
     	if(sd_cs == 1) buffer_rptr <= 9'd0;
 
   | 
||
| 
     	else 		      buffer_rptr <= buffer_rptr + 9'd1;
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     // ---------------- buffer write engine -----------------------
 
   | 
||
| 
     wire [7:0] buffer_din = reading?io_din:write_data;
 
   | 
||
| 
     wire buffer_din_strobe = reading?io_din_strobe:write_strobe;
 
   | 
||
| 
     | 
||
| 
     always @(negedge buffer_din_strobe or posedge sd_cs) begin
 
   | 
||
| 
     	if(sd_cs == 1) begin
 
   | 
||
| 
     		buffer_wptr <= 9'd0;
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     		buffer[buffer_wptr] <= buffer_din;	
 
   | 
||
| 
     		buffer_wptr <= buffer_wptr + 9'd1;
 
   | 
||
| 
     	end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     wire [7:0] WRITE_DATA_RESPONSE = 8'h05;
 
   | 
||
| 
     | 
||
| 
     // ------------------------- CSD/CID BUFFER ----------------------
 
   | 
||
| 
     assign io_conf = (csd_wptr == 0);
 
   | 
||
| 
     | 
||
| 
     // the 32 bytes as sent from the io controller
 
   | 
||
| 
     reg [7:0] cid [15:0];
 
   | 
||
| 
     reg [7:0] csd [15:0];
 
   | 
||
| 
     reg [7:0] conf;
 
   | 
||
| 
     | 
||
| 
     reg [7:0] cid_byte;
 
   | 
||
| 
     reg [7:0] csd_byte;
 
   | 
||
| 
     reg [5:0] csd_wptr = 6'd0;
 
   | 
||
| 
     | 
||
| 
     // conf[0]==1 -> io controller is using an sdhc card
 
   | 
||
| 
     wire io_has_sdhc = conf[0];
 
   | 
||
| 
     assign io_sdhc = allow_sdhc && io_has_sdhc;
 
   | 
||
| 
     | 
||
| 
     always @(negedge io_din_strobe) begin
 
   | 
||
| 
     	// if io controller sends data without asserting io_ack, then it's
 
   | 
||
| 
     	// updating the config
 
   | 
||
| 
     	if(!io_ack && (csd_wptr <= 32)) begin
 
   | 
||
| 
     | 
||
| 
     		if(csd_wptr < 16)                       // first 16 bytes are cid
 
   | 
||
| 
     			cid[csd_wptr] <= io_din;	
 
   | 
||
| 
     		if((csd_wptr >= 16) && (csd_wptr < 32)) // then comes csd
 
   | 
||
| 
     			csd[csd_wptr-16] <= io_din;	
 
   | 
||
| 
     		if(csd_wptr == 32)                      // finally a config byte
 
   | 
||
| 
     			conf <= io_din;	
 
   | 
||
| 
     | 
||
| 
     		csd_wptr	<= csd_wptr + 1;
 
   | 
||
| 
     	end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     always @(posedge buffer_read_latch)
 
   | 
||
| 
     	cid_byte <= cid[buffer_rptr];
 
   | 
||
| 
     | 
||
| 
     always @(posedge buffer_read_latch)
 
   | 
||
| 
     	csd_byte <= csd[buffer_rptr];
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     // ----------------- spi transmitter --------------------
 
   | 
||
| 
     always@(negedge sd_sck or posedge sd_cs) begin
 
   | 
||
| 
     	if(sd_cs == 1) begin
 
   | 
||
| 
     	   sd_sdo <= 1'b1;
 
   | 
||
| 
     		read_state <= 3'd0;
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     		core_buffer_read_strobe <= 1'b0;
 
   | 
||
| 
     | 
||
| 
     		// bring io ack in local clock domain
 
   | 
||
| 
     		io_ackD <= io_ack;
 
   | 
||
| 
     		io_ackD2 <= io_ackD;
 
   | 
||
| 
     | 
||
| 
     		// -------- catch read commmand and reset read state machine ------
 
   | 
||
| 
     		if(bit_cnt == 7) begin
 
   | 
||
| 
     			if(cmd_cnt == 5) begin
 
   | 
||
| 
     				// CMD17: READ_SINGLE_BLOCK
 
   | 
||
| 
     				if(cmd == 8'h51)
 
   | 
||
| 
     					read_state <= 3'd1;      // start waiting for data from io controller
 
   | 
||
| 
     			end
 
   | 
||
| 
     		end
 
   | 
||
| 
     | 
||
| 
           if(byte_cnt < 6+NCR) begin
 
   | 
||
| 
     		  sd_sdo <= 1'b1;				// reply $ff -> wait
 
   | 
||
| 
     		end else begin
 
   | 
||
| 
     | 
||
| 
     			if(byte_cnt == 6+NCR) begin
 
   | 
||
| 
     				sd_sdo <= reply[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     				if(bit_cnt == 7) begin
 
   | 
||
| 
     					// CMD9: SEND_CSD
 
   | 
||
| 
     					// CMD10: SEND_CID
 
   | 
||
| 
     					if((cmd == 8'h49)||(cmd == 8'h4a))
 
   | 
||
| 
     						read_state <= 3'd3;      // jump directly to data transmission
 
   | 
||
| 
     				end
 
   | 
||
| 
     			end
 
   | 
||
| 
     			else if((reply_len > 0) && (byte_cnt == 6+NCR+1))
 
   | 
||
| 
     				sd_sdo <= reply0[~bit_cnt];
 
   | 
||
| 
     			else if((reply_len > 1) && (byte_cnt == 6+NCR+2))
 
   | 
||
| 
     				sd_sdo <= reply1[~bit_cnt];
 
   | 
||
| 
     			else if((reply_len > 2) && (byte_cnt == 6+NCR+3))
 
   | 
||
| 
     				sd_sdo <= reply2[~bit_cnt];
 
   | 
||
| 
     			else if((reply_len > 3) && (byte_cnt == 6+NCR+4))
 
   | 
||
| 
     				sd_sdo <= reply3[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     			else
 
   | 
||
| 
     				sd_sdo <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     			// falling edge of io_ack signals end of incoming data stream
 
   | 
||
| 
     			if((read_state == 3'd1) && !io_ackD && io_ackD2) 
 
   | 
||
| 
     				read_state <= 3'd2;
 
   | 
||
| 
     | 
||
| 
     			// wait for begin of new byte
 
   | 
||
| 
     			if((read_state == 3'd2) && (bit_cnt == 7))
 
   | 
||
| 
     				read_state <= 3'd3;
 
   | 
||
| 
     | 
||
| 
     			// send data token
 
   | 
||
| 
     			if(read_state == 3'd3) begin
 
   | 
||
| 
     				sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     				if(bit_cnt == 7)
 
   | 
||
| 
     					read_state <= 3'd4;   // next: send data
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// send data
 
   | 
||
| 
     			if(read_state == 3'd4) begin
 
   | 
||
| 
     				if(cmd == 8'h51) 							// CMD17: READ_SINGLE_BLOCK
 
   | 
||
| 
     					sd_sdo <= buffer_byte[~bit_cnt];
 
   | 
||
| 
     				else if(cmd == 8'h49) 					// CMD9: SEND_CSD
 
   | 
||
| 
     					sd_sdo <= csd_byte[~bit_cnt];
 
   | 
||
| 
     				else if(cmd == 8'h4a) 					// CMD10: SEND_CID
 
   | 
||
| 
     					sd_sdo <= cid_byte[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     				if(bit_cnt == 7) begin
 
   | 
||
| 
     					core_buffer_read_strobe <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     					// send 512 sector data bytes?
 
   | 
||
| 
     					if((cmd == 8'h51) && (buffer_rptr == 511))
 
   | 
||
| 
     						read_state <= 3'd5;   // next: send crc
 
   | 
||
| 
     | 
||
| 
     					// send 16 cid/csd data bytes?
 
   | 
||
| 
     					if(((cmd == 8'h49)||(cmd == 8'h4a)) && (buffer_rptr == 15))
 
   | 
||
| 
     						read_state <= 3'd0;   // return to idle state
 
   | 
||
| 
     				end
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// send crc[0]
 
   | 
||
| 
     			if(read_state == 3'd5) begin
 
   | 
||
| 
     				sd_sdo <= 1'b1;
 
   | 
||
| 
     				if(bit_cnt == 7)
 
   | 
||
| 
     					read_state <= 3'd6;  // send second crc byte
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// send crc[1]
 
   | 
||
| 
     			if(read_state == 3'd6) begin
 
   | 
||
| 
     				sd_sdo <= 1'b1;
 
   | 
||
| 
     				if(bit_cnt == 7)
 
   | 
||
| 
     					read_state <= 3'd0;  // return to idle state
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// send write data response
 
   | 
||
| 
     			if(write_state == 3'd5) 
 
   | 
||
| 
     				sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     			// busy after write until the io controller sends ack
 
   | 
||
| 
     			if(write_state == 3'd6) 
 
   | 
||
| 
     				sd_sdo <= 1'b0;
 
   | 
||
| 
     		end
 
   | 
||
| 
        end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     // spi receiver  
 
   | 
||
| 
     always @(posedge sd_sck or posedge sd_cs) begin
 
   | 
||
| 
     	// cs is active low
 
   | 
||
| 
     	if(sd_cs == 1) begin
 
   | 
||
| 
     		bit_cnt <= 3'd0;
 
   | 
||
| 
     		byte_cnt <= 8'd0;
 
   | 
||
| 
     		cmd_cnt <= 8'd0;
 
   | 
||
| 
     		write_state <= 3'd0;
 
   | 
||
| 
     		write_strobe <= 1'b0;
 
   | 
||
| 
     	end else begin 
 
   | 
||
| 
     		write_strobe <= 1'b0;
 
   | 
||
| 
     		sbuf[6:0] <= { sbuf[5:0], sd_sdi };
 
   | 
||
| 
     		bit_cnt <= bit_cnt + 3'd1;
 
   | 
||
| 
     | 
||
| 
     		if((bit_cnt == 7)&&(byte_cnt != 255)) begin
 
   | 
||
| 
     			byte_cnt <= byte_cnt + 8'd1;			
 
   | 
||
| 
     | 
||
| 
     			if(cmd_cnt == 0) begin
 
   | 
||
| 
     				// first byte of valid command is 01xxxxxx
 
   | 
||
| 
     				if((write_state == 3'd0) && sbuf[6:5] == 2'b01) begin
 
   | 
||
| 
     					cmd_cnt <= 8'd1;			
 
   | 
||
| 
     					byte_cnt <= 8'd1;			
 
   | 
||
| 
     				end
 
   | 
||
| 
     			end else if(cmd_cnt < 6)
 
   | 
||
| 
     				cmd_cnt <= cmd_cnt + 8'd1;
 
   | 
||
| 
     			else
 
   | 
||
| 
     				// command counting stops after last command byte. 
 
   | 
||
| 
     				cmd_cnt <= 8'd0;
 
   | 
||
| 
     		end
 
   | 
||
| 
     | 
||
| 
     		// finished reading command byte
 
   | 
||
| 
           if(bit_cnt == 7) begin
 
   | 
||
| 
     | 
||
| 
     			// don't accept new commands once a write command has been accepted
 
   | 
||
| 
     			if((write_state == 3'd0) && (cmd_cnt == 0)&&(sbuf[6:5] == 2'b01)) begin
 
   | 
||
| 
     				cmd <= { sbuf, sd_sdi};
 
   | 
||
| 
     | 
||
| 
     			   // set cmd55 flag if previous command was 55
 
   | 
||
| 
     			   cmd55 <= (cmd == 8'h77);
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// parse additional command bytes
 
   | 
||
| 
     			if(cmd_cnt == 1) lba3 <= { sbuf, sd_sdi};
 
   | 
||
| 
     			if(cmd_cnt == 2) lba2 <= { sbuf, sd_sdi};
 
   | 
||
| 
     			if(cmd_cnt == 3) lba1 <= { sbuf, sd_sdi};
 
   | 
||
| 
     			if(cmd_cnt == 4) lba0 <= { sbuf, sd_sdi};			
 
   | 
||
| 
     			if(cmd_cnt == 5) crc  <= { sbuf, sd_sdi};
 
   | 
||
| 
     | 
||
| 
     			// last byte received, evaluate
 
   | 
||
| 
     			if(cmd_cnt == 5) begin
 
   | 
||
| 
     				// default:
 
   | 
||
| 
     				reply <= 8'h04;     // illegal command
 
   | 
||
| 
     				reply_len <= 4'd0;  // no extra reply bytes
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     				// CMD0: GO_IDLE_STATE
 
   | 
||
| 
     				if(cmd == 8'h40)
 
   | 
||
| 
     					reply <= 8'h01;    // ok, busy
 
   | 
||
| 
     | 
||
| 
     				// CMD1: SEND_OP_COND
 
   | 
||
| 
     				else if(cmd == 8'h41)
 
   | 
||
| 
     					reply <= 8'h00;    // ok, not busy
 
   | 
||
| 
     | 
||
| 
     				// CMD8: SEND_IF_COND (V2 only)
 
   | 
||
| 
     				else if(cmd == 8'h48) begin
 
   | 
||
| 
     					reply <= 8'h01;    // ok, busy
 
   | 
||
| 
     					reply0 <= 8'h00;
 
   | 
||
| 
     					reply1 <= 8'h00;
 
   | 
||
| 
     					reply2 <= 8'h01;
 
   | 
||
| 
     					reply3 <= 8'hAA;
 
   | 
||
| 
     					reply_len <= 4'd4;
 
   | 
||
| 
     				end
 
   | 
||
| 
     | 
||
| 
     				// CMD9: SEND_CSD
 
   | 
||
| 
     				else if(cmd == 8'h49)
 
   | 
||
| 
     					reply <= 8'h00;    // ok
 
   | 
||
| 
     | 
||
| 
     				// CMD10: SEND_CID
 
   | 
||
| 
     				else if(cmd == 8'h4a)
 
   | 
||
| 
     					reply <= 8'h00;    // ok
 
   | 
||
| 
     | 
||
| 
     				// CMD16: SET_BLOCKLEN
 
   | 
||
| 
     				else if(cmd == 8'h50) begin
 
   | 
||
| 
     				   // we only support a block size of 512
 
   | 
||
| 
     				   if(io_lba == 32'd512)
 
   | 
||
| 
     						reply <= 8'h00;    // ok
 
   | 
||
| 
     				   else
 
   | 
||
| 
     						reply <= 8'h40;    // parmeter error
 
   | 
||
| 
     				end
 
   | 
||
| 
     | 
||
| 
     				// CMD17: READ_SINGLE_BLOCK
 
   | 
||
| 
     				else if(cmd == 8'h51)
 
   | 
||
| 
     					reply <= 8'h00;    // ok
 
   | 
||
| 
     | 
||
| 
     				// CMD24: WRITE_BLOCK
 
   | 
||
| 
     				else if(cmd == 8'h58) begin
 
   | 
||
| 
     					reply <= 8'h00;    // ok
 
   | 
||
| 
     					write_state <= 3'd1;  // expect data token
 
   | 
||
| 
     				end
 
   | 
||
| 
     | 
||
| 
     			   // ACMD41: APP_SEND_OP_COND
 
   | 
||
| 
     			   else if(cmd55 && (cmd == 8'h69))
 
   | 
||
| 
     					reply <= 8'h00;    // ok, not busy
 
   | 
||
| 
     | 
||
| 
     				// CMD55: APP_COND
 
   | 
||
| 
     				else if(cmd == 8'h77)
 
   | 
||
| 
     					reply <= 8'h01;    // ok, busy
 
   | 
||
| 
     | 
||
| 
     				// CMD58: READ_OCR
 
   | 
||
| 
     				else if(cmd == 8'h7a) begin
 
   | 
||
| 
     					reply <= 8'h00;    // ok
 
   | 
||
| 
     | 
||
| 
     					reply0 <= OCR[31:24];   // bit 30 = 1 -> high capacity card 
 
   | 
||
| 
     					reply1 <= OCR[23:16];
 
   | 
||
| 
     					reply2 <= OCR[15:8];
 
   | 
||
| 
     					reply3 <= OCR[7:0];
 
   | 
||
| 
     					reply_len <= 4'd4;
 
   | 
||
| 
     				end
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// ---------- handle write -----------
 
   | 
||
| 
     | 
||
| 
     			// waiting for data token
 
   | 
||
| 
     			if(write_state == 3'd1) begin
 
   | 
||
| 
     				if({ sbuf, sd_sdi} == 8'hfe )
 
   | 
||
| 
     					write_state <= 3'd2;
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// transfer 512 bytes
 
   | 
||
| 
     			if(write_state == 3'd2) begin
 
   | 
||
| 
     				// push one byte into local buffer
 
   | 
||
| 
     				write_strobe <= 1'b1;
 
   | 
||
| 
     				write_data <= { sbuf, sd_sdi};
 
   | 
||
| 
     | 
||
| 
     				if(buffer_wptr == 511)
 
   | 
||
| 
     					write_state <= 3'd3;
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// transfer 1st crc byte
 
   | 
||
| 
     			if(write_state == 3'd3)
 
   | 
||
| 
     				write_state <= 3'd4;
 
   | 
||
| 
     | 
||
| 
     			// transfer 2nd crc byte
 
   | 
||
| 
     			if(write_state == 3'd4)
 
   | 
||
| 
     				write_state <= 3'd5;
 
   | 
||
| 
     | 
||
| 
     			// send data response
 
   | 
||
| 
     			if(write_state == 3'd5)
 
   | 
||
| 
     				write_state <= 3'd6;
 
   | 
||
| 
     		end
 
   | 
||
| 
     | 
||
| 
     		// wait for io controller to accept data
 
   | 
||
| 
     		// this happens outside the bit_cnt == 7 test as the 
 
   | 
||
| 
     		// transition may happen at any time
 
   | 
||
| 
     		if(write_state == 3'd6 && !io_ackD && io_ackD2)
 
   | 
||
| 
     			write_state <= 3'd0;
 
   | 
||
| 
     	end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     endmodule
 
   | 
||
| mist/user_io.v | ||
|---|---|---|
| 
     // MiST user_io
 
   | 
||
| 
     | 
||
| 
     module user_io(
 
   | 
||
| 
     	input      		SPI_CLK,
 
   | 
||
| 
     	input      		SPI_SS_IO,
 
   | 
||
| 
     	output     		reg SPI_MISO,
 
   | 
||
| 
     	input      		SPI_MOSI,
 
   | 
||
| 
     | 
||
| 
     	input [7:0] 	CORE_TYPE,
 
   | 
||
| 
     | 
||
| 
     	output [5:0] 	JOY0,
 
   | 
||
| 
     	output [5:0] 	JOY1,
 
   | 
||
| 
     	output [1:0] 	BUTTONS,
 
   | 
||
| 
     	output [1:0] 	SWITCHES,
 
   | 
||
| 
     | 
||
| 
     	input 	  		clk,
 
   | 
||
| 
     	output	 		ps2_clk,
 
   | 
||
| 
     	output reg 		ps2_data
 
   | 
||
| 
     );
 
   | 
||
| 
     | 
||
| 
     reg [6:0]         sbuf;
 
   | 
||
| 
     reg [7:0]         cmd;
 
   | 
||
| 
     reg [4:0] 	      cnt;
 
   | 
||
| 
     reg [5:0]         joystick0;
 
   | 
||
| 
     reg [5:0]         joystick1;
 
   | 
||
| 
     reg [3:0] 	      but_sw;
 
   | 
||
| 
     | 
||
| 
     assign JOY0 = joystick0;
 
   | 
||
| 
     assign JOY1 = joystick1;
 
   | 
||
| 
     assign BUTTONS = but_sw[1:0];
 
   | 
||
| 
     assign SWITCHES = but_sw[3:2];
 
   | 
||
| 
     | 
||
| 
     // drive MISO only when transmitting core id
 
   | 
||
| 
     always@(negedge SPI_CLK or posedge SPI_SS_IO) begin
 
   | 
||
| 
     	if(SPI_SS_IO == 1) begin
 
   | 
||
| 
     	   SPI_MISO <= 1'bZ;
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
           if(cnt < 8) begin
 
   | 
||
| 
     		  SPI_MISO <= CORE_TYPE[7-cnt];
 
   | 
||
| 
     		end else begin
 
   | 
||
| 
     	     SPI_MISO <= 1'bZ;
 
   | 
||
| 
     		end
 
   | 
||
| 
        end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     // 8 byte fifo to store ps2 bytes
 
   | 
||
| 
     localparam PS2_FIFO_BITS = 3;
 
   | 
||
| 
     reg [7:0] ps2_fifo [(2**PS2_FIFO_BITS)-1:0];
 
   | 
||
| 
     reg [PS2_FIFO_BITS-1:0] ps2_wptr;
 
   | 
||
| 
     reg [PS2_FIFO_BITS-1:0] ps2_rptr;
 
   | 
||
| 
     | 
||
| 
     // ps2 transmitter state machine
 
   | 
||
| 
     reg [3:0] ps2_tx_state;
 
   | 
||
| 
     reg [7:0] ps2_tx_byte;
 
   | 
||
| 
     reg ps2_parity;
 
   | 
||
| 
     | 
||
| 
     assign ps2_clk = clk || (ps2_tx_state == 0);
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     // ps2 transmitter
 
   | 
||
| 
     // Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
 
   | 
||
| 
     reg ps2_r_inc;
 
   | 
||
| 
     always@(posedge clk) begin
 
   | 
||
| 
     	ps2_r_inc <= 1'b0;
 
   | 
||
| 
     | 
||
| 
     	if(ps2_r_inc)
 
   | 
||
| 
     		ps2_rptr <= ps2_rptr + 1;
 
   | 
||
| 
     | 
||
| 
     	// transmitter is idle?
 
   | 
||
| 
     	if(ps2_tx_state == 0) begin
 
   | 
||
| 
     		// data in fifo present?
 
   | 
||
| 
     		if(ps2_wptr != ps2_rptr) begin
 
   | 
||
| 
     			// load tx register from fifo
 
   | 
||
| 
     			ps2_tx_byte <= ps2_fifo[ps2_rptr];
 
   | 
||
| 
     			ps2_r_inc <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     			// reset parity
 
   | 
||
| 
     			ps2_parity <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     			// start transmitter
 
   | 
||
| 
     			ps2_tx_state <= 4'd1;
 
   | 
||
| 
     | 
||
| 
     			// put start bit on data line
 
   | 
||
| 
     			ps2_data <= 1'b0;			// start bit is 0
 
   | 
||
| 
     		end
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     | 
||
| 
     		// transmission of 8 data bits
 
   | 
||
| 
     		if((ps2_tx_state >= 1)&&(ps2_tx_state < 9)) begin
 
   | 
||
| 
     			ps2_data <= ps2_tx_byte[0];			  // data bits
 
   | 
||
| 
     			ps2_tx_byte[6:0] <= ps2_tx_byte[7:1]; // shift down
 
   | 
||
| 
     			if(ps2_tx_byte[0]) 
 
   | 
||
| 
     				ps2_parity <= !ps2_parity;
 
   | 
||
| 
     		end
 
   | 
||
| 
     | 
||
| 
     		// transmission of parity
 
   | 
||
| 
     		if(ps2_tx_state == 9)
 
   | 
||
| 
     			ps2_data <= ps2_parity;
 
   | 
||
| 
     | 
||
| 
     		// transmission of stop bit
 
   | 
||
| 
     		if(ps2_tx_state == 10)
 
   | 
||
| 
     			ps2_data <= 1'b1;			// stop bit is 1
 
   | 
||
| 
     | 
||
| 
     		// advance state machine
 
   | 
||
| 
     		if(ps2_tx_state < 11)
 
   | 
||
| 
     			ps2_tx_state <= ps2_tx_state + 4'd1;
 
   | 
||
| 
     		else	
 
   | 
||
| 
     			ps2_tx_state <= 4'd0;
 
   | 
||
| 
     | 
||
| 
     	end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     // SPI receiver
 
   | 
||
| 
     //reg ps2_w_inc;
 
   | 
||
| 
     always@(posedge SPI_CLK or posedge SPI_SS_IO) begin
 
   | 
||
| 
     //	ps2_w_inc <= 1'b0;
 
   | 
||
| 
     //	if(ps2_w_inc)
 
   | 
||
| 
     //		ps2_wptr <= ps2_wptr + 1;
 
   | 
||
| 
     | 
||
| 
     	if(SPI_SS_IO == 1) begin
 
   | 
||
| 
     	   cnt <= 1'b0;
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     		sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
 
   | 
||
| 
     		// counter counts 0-7, 8-15, 8-15 ...
 
   | 
||
| 
     		// 0-7 is command, 8-15 is payload
 
   | 
||
| 
     		if(cnt != 15)  cnt <= cnt + 4'd1;
 
   | 
||
| 
     		else				cnt <= 4'd8;
 
   | 
||
| 
     | 
||
| 
     		// finished reading command byte
 
   | 
||
| 
           if(cnt == 7)
 
   | 
||
| 
     		   cmd <= { sbuf, SPI_MOSI};
 
   | 
||
| 
     | 
||
| 
           if(cnt == 15) begin
 
   | 
||
| 
     		   if(cmd == 1)
 
   | 
||
| 
     				but_sw <= { sbuf[2:0], SPI_MOSI }; 
 
   | 
||
| 
     | 
||
| 
     			if(cmd == 2)
 
   | 
||
| 
     				joystick0 <= { sbuf[4:0], SPI_MOSI };
 
   | 
||
| 
     | 
||
| 
     			if(cmd == 3)
 
   | 
||
| 
     				joystick1 <= { sbuf[4:0], SPI_MOSI };
 
   | 
||
| 
     | 
||
| 
     		   if(cmd == 5) begin
 
   | 
||
| 
     				// store incoming keyboard bytes in 
 
   | 
||
| 
     				ps2_fifo[ps2_wptr] <= { sbuf, SPI_MOSI }; 
 
   | 
||
| 
     				ps2_wptr <= ps2_wptr + 1;
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     		end	
 
   | 
||
| 
     	end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     endmodule
 
   | 
||
| 
     //
 
   | 
||
| 
     // user_io.v
 
   | 
||
| 
     //
 
   | 
||
| 
     // user_io for the MiST board
 
   | 
||
| 
     // http://code.google.com/p/mist-board/
 
   | 
||
| 
     //
 
   | 
||
| 
     // Copyright (c) 2014 Till Harbaum <till@harbaum.org>
 
   | 
||
| 
     //
 
   | 
||
| 
     // 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 <http://www.gnu.org/licenses/>.
 
   | 
||
| 
     //
 
   | 
||
| 
     | 
||
| 
     // parameter STRLEN and the actual length of conf_str have to match
 
   | 
||
| 
     | 
||
| 
     module user_io #(parameter STRLEN=0) (
 
   | 
||
| 
     	input [(8*STRLEN)-1:0] conf_str,
 
   | 
||
| 
     | 
||
| 
     	input      		SPI_CLK,
 
   | 
||
| 
     	input      		SPI_SS_IO,
 
   | 
||
| 
     	output     		reg SPI_MISO,
 
   | 
||
| 
     	input      		SPI_MOSI,
 
   | 
||
| 
     | 
||
| 
     	output reg [5:0] 	joystick_0,
 
   | 
||
| 
     	output reg [5:0] 	joystick_1,
 
   | 
||
| 
     	output reg [15:0] joystick_analog_0,
 
   | 
||
| 
     	output reg [15:0] joystick_analog_1,
 
   | 
||
| 
     	output [1:0] 		buttons,
 
   | 
||
| 
     	output [1:0] 		switches,
 
   | 
||
| 
     | 
||
| 
     	output reg [7:0]   status,
 
   | 
||
| 
     | 
||
| 
     	// connection to sd card emulation
 
   | 
||
| 
     	input [31:0]  sd_lba,
 
   | 
||
| 
     	input         sd_rd,
 
   | 
||
| 
     	input         sd_wr,
 
   | 
||
| 
     	output reg	  sd_ack,
 
   | 
||
| 
     	input         sd_conf,
 
   | 
||
| 
     	input         sd_sdhc,
 
   | 
||
| 
     	output reg [7:0]  sd_dout,
 
   | 
||
| 
     	output reg	  sd_dout_strobe,
 
   | 
||
| 
     	input [7:0]   sd_din,
 
   | 
||
| 
     	output reg 	  sd_din_strobe,
 
   | 
||
| 
     | 
||
| 
     | 
||
| 
     	// ps2 keyboard emulation
 
   | 
||
| 
     	input 	  		ps2_clk,				// 12-16khz provided by core
 
   | 
||
| 
     	output	 		ps2_kbd_clk,
 
   | 
||
| 
     	output reg 		ps2_kbd_data,
 
   | 
||
| 
     | 
||
| 
     	// serial com port 
 
   | 
||
| 
     	input [7:0]		serial_data,
 
   | 
||
| 
     	input				serial_strobe
 
   | 
||
| 
     );
 
   | 
||
| 
     | 
||
| 
     reg [6:0]         sbuf;
 
   | 
||
| 
     reg [7:0]         cmd;
 
   | 
||
| 
     reg [2:0] 	      bit_cnt;    // counts bits 0-7 0-7 ...
 
   | 
||
| 
     reg [7:0]         byte_cnt;   // counts bytes
 
   | 
||
| 
     reg [5:0]         joystick0;
 
   | 
||
| 
     reg [5:0]         joystick1;
 
   | 
||
| 
     reg [3:0] 	      but_sw;
 
   | 
||
| 
     reg [2:0]         stick_idx;
 
   | 
||
| 
     | 
||
| 
     assign buttons = but_sw[1:0];
 
   | 
||
| 
     assign switches = but_sw[3:2];
 
   | 
||
| 
     | 
||
| 
     // this variant of user_io is for 8 bit cores (type == a4) only
 
   | 
||
| 
     wire [7:0] core_type = 8'ha4;
 
   | 
||
| 
     | 
||
| 
     // command byte read by the io controller
 
   | 
||
| 
     wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
 
   | 
||
| 
     | 
||
| 
     // filter spi clock. the 8 bit gate delay is ~2.5ns in total
 
   | 
||
| 
     wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */;
 
   | 
||
| 
     wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
 
   | 
||
| 
     | 
||
| 
     // drive MISO only when transmitting core id
 
   | 
||
| 
     always@(negedge spi_sck or posedge SPI_SS_IO) begin
 
   | 
||
| 
     	if(SPI_SS_IO == 1) begin
 
   | 
||
| 
     	   SPI_MISO <= 1'bZ;
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     | 
||
| 
     		// first byte returned is always core type, further bytes are 
 
   | 
||
| 
     		// command dependent
 
   | 
||
| 
           if(byte_cnt == 0) begin
 
   | 
||
| 
     		  SPI_MISO <= core_type[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     		end else begin
 
   | 
||
| 
     			// reading serial fifo
 
   | 
||
| 
     		   if(cmd == 8'h1b) begin
 
   | 
||
| 
     				// send alternating flag byte and data
 
   | 
||
| 
     				if(byte_cnt[0]) 	SPI_MISO <= serial_out_status[~bit_cnt];
 
   | 
||
| 
     				else					SPI_MISO <= serial_out_byte[~bit_cnt];
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// reading config string
 
   | 
||
| 
     		   else if(cmd == 8'h14) begin
 
   | 
||
| 
     				// returning a byte from string
 
   | 
||
| 
     				if(byte_cnt < STRLEN + 1)
 
   | 
||
| 
     					SPI_MISO <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
 
   | 
||
| 
     				else
 
   | 
||
| 
     					SPI_MISO <= 1'b0;
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// reading sd card status
 
   | 
||
| 
     		   else if(cmd == 8'h16) begin
 
   | 
||
| 
     				if(byte_cnt == 1)
 
   | 
||
| 
     					SPI_MISO <= sd_cmd[~bit_cnt];
 
   | 
||
| 
     				else if((byte_cnt >= 2) && (byte_cnt < 6))
 
   | 
||
| 
     					SPI_MISO <= sd_lba[{5-byte_cnt, ~bit_cnt}];
 
   | 
||
| 
     				else
 
   | 
||
| 
     					SPI_MISO <= 1'b0;
 
   | 
||
| 
     			end
 
   | 
||
| 
     | 
||
| 
     			// reading sd card write data
 
   | 
||
| 
     		   else if(cmd == 8'h18)
 
   | 
||
| 
     				SPI_MISO <= sd_din[~bit_cnt];
 
   | 
||
| 
     | 
||
| 
     			else
 
   | 
||
| 
     				SPI_MISO <= 1'b0;
 
   | 
||
| 
     		end
 
   | 
||
| 
        end
 
   | 
||
| 
     end
 
   | 
||
| 
     | 
||
| 
     // 8 byte fifo to store ps2 bytes
 
   | 
||
| 
     localparam PS2_FIFO_BITS = 3;
 
   | 
||
| 
     reg [7:0] ps2_fifo [(2**PS2_FIFO_BITS)-1:0];
 
   | 
||
| 
     reg [PS2_FIFO_BITS-1:0] ps2_wptr;
 
   | 
||
| 
     reg [PS2_FIFO_BITS-1:0] ps2_rptr;
 
   | 
||
| 
     | 
||
| 
     // ps2 transmitter state machine
 
   | 
||
| 
     reg [3:0] ps2_tx_state;
 
   | 
||
| 
     reg [7:0] ps2_tx_byte;
 
   | 
||
| 
     reg ps2_parity;
 
   | 
||
| 
     | 
||
| 
     assign ps2_kbd_clk = ps2_clk || (ps2_tx_state == 0);
 
   | 
||
| 
     | 
||
| 
     // ps2 transmitter
 
   | 
||
| 
     // Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
 
   | 
||
| 
     reg ps2_r_inc;
 
   | 
||
| 
     always@(posedge ps2_clk) begin
 
   | 
||
| 
     	ps2_r_inc <= 1'b0;
 
   | 
||
| 
     | 
||
| 
     	if(ps2_r_inc)
 
   | 
||
| 
     		ps2_rptr <= ps2_rptr + 1;
 
   | 
||
| 
     | 
||
| 
     	// transmitter is idle?
 
   | 
||
| 
     	if(ps2_tx_state == 0) begin
 
   | 
||
| 
     		// data in fifo present?
 
   | 
||
| 
     		if(ps2_wptr != ps2_rptr) begin
 
   | 
||
| 
     			// load tx register from fifo
 
   | 
||
| 
     			ps2_tx_byte <= ps2_fifo[ps2_rptr];
 
   | 
||
| 
     			ps2_r_inc <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     			// reset parity
 
   | 
||
| 
     			ps2_parity <= 1'b1;
 
   | 
||
| 
     | 
||
| 
     			// start transmitter
 
   | 
||
| 
     			ps2_tx_state <= 4'd1;
 
   | 
||
| 
     | 
||
| 
     			// put start bit on data line
 
   | 
||
| 
     			ps2_kbd_data <= 1'b0;			// start bit is 0
 
   | 
||
| 
     		end
 
   | 
||
| 
     	end else begin
 
   | 
||
| 
     | 
||
| 
     		// transmission of 8 data bits
 
   | 
||
| 
     		if((ps2_tx_state >= 1)&&(ps2_tx_state < 9)) begin
 
   | 
||
| 
     			ps2_kbd_data <= ps2_tx_byte[0];			  // data bits
 
   | 
||
| 
     			ps2_tx_byte[6:0] <= ps2_tx_byte[7:1]; // shift down
 
   | 
||
| 
     			if(ps2_tx_byte[0]) 
 
   | 
||
| 
     				ps2_parity <= !ps2_parity;
 
   | 
||
| 
     		end
 
   | 
||
| 
     | 
||
| 
     		// transmission of parity
 
   | 
||
| 
     		if(ps2_tx_state == 9)
 
   | 
||
| 
     			ps2_kbd_data <= ps2_parity;
 
   | 
||
| 
     | 
||
| 
     		// transmission of stop bit
 
   | 
||
| 
     		if(ps2_tx_state == 10)
 
   | 
||
| 
     			ps2_kbd_data <= 1'b1;			// stop bit is 1
 
   | 
||
| 
     | 
||
| 
     		// advance state machine
 
   | 
||
Changed mist to use simulated sd card, rather than the custom protocol