library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.numeric_std.all; -- Uncomment the following lines to use the declarations that are -- provided for instantiating Xilinx primitive components. --library UNISIM; --use UNISIM.VComponents.all; entity n64_cart is port( --usb PA : inout std_logic_vector(2 downto 0); PB : inout std_logic_vector(7 downto 0); PD : inout std_logic_vector(7 downto 0); CTL0 : in std_logic; CTL1 : in std_logic; CTL2 : in std_logic; RDY0 : out std_logic; IFCLK : in std_logic; --dram DQ : inout std_logic_vector(15 downto 0); WE : out std_logic; RE : out std_logic; RAS : out std_logic; CAS : out std_logic; CS : out std_logic; DRAM_CLK : out std_logic; BA : out std_logic_vector(1 downto 0); A : out std_logic_vector(12 downto 0); --n64 AD : inout std_logic_vector(15 downto 0); write : in std_logic; read : in std_logic; reset : in std_logic; ALE_H : in std_logic; ALE_L : in std_logic; n64_clk : in std_logic; n64_cold_reset : in std_logic; --n64 devices eeprom : inout std_logic; serial_clk : in std_logic; unused : out std_logic ); end n64_cart; architecture Behavioral of n64_cart is signal pc_address : std_logic_vector(31 downto 0); signal n64_address : std_logic_vector(31 downto 0); signal start_n64_address : std_logic_vector(31 downto 0); signal n64_state : integer:=0; signal FX2_data_out : std_logic_vector(15 downto 0); signal temp_FX2_data_out : std_logic_vector(15 downto 0); signal FX2_data_in : std_logic_vector(15 downto 0); signal N64_data_out : std_logic_vector(15 downto 0); signal N64_data_in : std_logic_vector(15 downto 0); signal EEPROM_data_in : std_logic_vector(15 downto 0); signal EEPROM_data_out : std_logic_vector(15 downto 0); signal eeprom_address : std_logic_vector(31 downto 0); signal eeprom16k : std_logic:='0'; signal eeprom_dat : std_logic_vector(80 downto 0); --this should hold the largest transmitted data packet (add one for stop bit) signal eeprom_dat_out : std_logic_vector(64 downto 0); --add one for the stop bit signal eeprom_addr_count : std_logic_vector(3 downto 0); signal eeprom_op_done : std_logic:='0'; signal EEPROM_STATE : integer range 0 to 50:=0; signal refresh_dram : std_logic:='0'; signal refresh_count : integer range 0 to 1000:=0; signal DRAM_STATE : integer:=0; signal NEXT_STATE : integer:=0; signal clk_delay : integer range 0 to 255:=0; signal dram_clk_count : integer range 0 to 255:=0; signal pc_dram_op : integer range 0 to 3:=0; signal n64_dram_op : integer range 0 to 3:=0; signal eeprom_dram_op : integer range 0 to 3:=0; signal msg_pc_dram_op : integer range 0 to 3:=0; signal dram_data : std_logic_vector(15 downto 0); signal read_counter : integer range 0 to 255:=0; signal sram_flag_write : std_logic:='0'; signal alel_1 : std_logic; signal alel_2 : std_logic; signal aleh_1 : std_logic; signal aleh_2 : std_logic; signal CLKIN_w, CLK2X_dll, CLK2X_g, CLK4X_dll, CLK4X_g : std_logic; signal CLK0_dll,IFCLK_G : std_logic; COMPONENT IBUF PORT(i: IN STD_LOGIC; o: OUT STD_LOGIC); END COMPONENT; COMPONENT BUFG PORT(i: IN STD_LOGIC; o: OUT STD_LOGIC); END COMPONENT; COMPONENT IBUFG PORT(i: IN STD_LOGIC; o: OUT STD_LOGIC); END COMPONENT; component CLKDLL port ( CLKIN : in std_ulogic := '0'; CLKFB : in std_ulogic := '0'; RST : in std_ulogic := '0'; CLK0 : out std_ulogic := '0'; CLK90 : out std_ulogic := '0'; CLK180 : out std_ulogic := '0'; CLK270 : out std_ulogic := '0'; CLK2X : out std_ulogic := '0'; CLKDV : out std_ulogic := '0'; LOCKED : out std_ulogic := '0'); end component; begin --u1: IBUF port map(I=>ALE_L, O=>alel_1); --u2: BUFG port map(I=>alel_1,O=>alel_2); u3: IBUF port map(I=>ALE_H, O=>aleh_1); u4: IBUF port map(I=>ALE_L, O=>alel_1); clkpad : IBUFG port map (I=>IFCLK, O=>CLKIN_w); clk2xg : BUFG port map (I=>CLK2X_dll, O=>CLK2X_g); clk1xg : BUFG port map (I=>CLK0_dll, O=>IFCLK_G); dll2x : CLKDLL port map (CLKIN=>CLKIN_w, CLKFB=>CLK2X_g, RST=>'0', CLK0=>CLK0_dll, CLK90=>open, CLK180=>open, CLK270=>open, CLK2X=>CLK2X_dll, CLKDV=>open, LOCKED=>open); PD<=FX2_data_out(7 downto 0) when CTL0='1' else (others=>'Z'); PB<=FX2_data_out(15 downto 8) when CTL0='1' else (others=>'Z'); DRAM_CLK<=CLK2X_g; unused<=eeprom; process(ALE_L,ALE_H) begin -- if(ALE_H='1' and alel_1='1')then if(aleh_1'Event and aleh_1='0')then start_n64_address(31 downto 16)<=AD; end if; -- if(ALE_H='0' and alel_1='1')then if(alel_1'Event and alel_1='0')then start_n64_address(15 downto 0)<=AD; end if; end process; process(IFCLK_G,CLK2X_g) variable select_word : std_logic:='0'; variable last_ale_h : std_logic:='0'; variable last_ale_l : std_logic:='0'; variable last_read : std_logic:='0'; variable last_write : std_logic:='0'; variable last_read2 : std_logic:='0'; variable last_write2 : std_logic:='0'; variable last_alel : std_logic:='0'; variable last_alel2 : std_logic:='0'; variable last_pc_dram_op : integer range 0 to 3:=0; variable last_pc_dram_op2 : integer range 0 to 3:=0; variable last_eeprom_state2 : integer; variable last_eeprom_state : integer; variable stall_fx2 : integer range 0 to 31:=0; begin -- RDY0=0 stall gpif, 1=proceed -- use PORTA bit 0 to select whether to RW the address pointer or RW dram -- CTL0= read(1) or write(0) operation -- CTL1= data validate(0) CTLx signal are asserted on rising edge of IFCLK when bmIFCLKPOL polarity in FX2 is set to normal '0' -- CTL2= 0 means GPIF is waiting for RDY0=1 -- if(IFCLK'Event and IFCLK='0')then if(IFCLK_G'Event and IFCLK_G='0')then --read write the dram address pointer if(PA(1)='1')then if(CTL0='0' and CTL1='0')then --update the address counter --n64_address<=n64_address(15 downto 0) & PB & PD; elsif(CTL0='1' and CTL1='0')then if(select_word='0')then FX2_data_out<=n64_address(31 downto 16); else FX2_data_out<=n64_address(15 downto 0); end if; select_word:=not select_word; end if; msg_pc_dram_op<=0; --dram is idle RDY0<='1'; elsif(PA(0)='1')then if(CTL0='0' and CTL1='0')then --update the address counter pc_address<=pc_address(15 downto 0) & PB & PD; elsif(CTL0='1' and CTL1='0')then if(select_word='0')then FX2_data_out<=pc_address(31 downto 16); else FX2_data_out<=pc_address(15 downto 0); end if; select_word:=not select_word; end if; msg_pc_dram_op<=0; --dram is idle RDY0<='1'; --read write DRAM data else select_word:='0'; FX2_data_out<=temp_FX2_data_out; --check if dram completed operation if(stall_fx2>=5 and msg_pc_dram_op/=0 and pc_dram_op=0)then if(CTL2='0')then RDY0<='1'; --gpif continue else pc_address<=pc_address+2; msg_pc_dram_op<=0; stall_fx2:=0; RDY0<='0'; end if; else RDY0<='0'; end if; if(stall_fx2<20)then stall_fx2:=stall_fx2+1; end if; if(CTL0='0' and CTL1='0')then --write dram FX2_data_in<=PB & PD; msg_pc_dram_op<=1; stall_fx2:=0; elsif(CTL0='1' and CTL1='0')then --read dram msg_pc_dram_op<=2; stall_fx2:=0; end if; end if; if(pc_address=X"AA160000")then --update the pc dram address with these majic numbers to select what eeprom we want to emulate eeprom16k<='1'; elsif(pc_address=X"AA040000")then eeprom16k<='0'; end if; end if; ------------------------------------------------------------------- --DRAM clock domain ------------------------------------------------------------------- if(CLK2X_g'Event and CLK2X_g='0')then --handle dram state machine dram_clk_count<=dram_clk_count+1; if(dram_clk_count>=clk_delay)then dram_clk_count<=0; DRAM_STATE<=NEXT_STATE; end if; --handle pc read write requests from that other clock domain if(last_pc_dram_op/=last_pc_dram_op2)then pc_dram_op<=last_pc_dram_op; end if; last_pc_dram_op2:=last_pc_dram_op; last_pc_dram_op:=msg_pc_dram_op; if(DRAM_STATE=7)then --reset op at this state pc_dram_op<=0; end if; --handle eeprom read write requests from other clock domain if(last_eeprom_state2=20)then --READ if(eeprom_addr_count=4)then eeprom_dram_op<=0; eeprom_dat_out<=eeprom_dat_out(63 downto 0) & '1'; --add a stop bit eeprom_addr_count<=eeprom_addr_count + 1; elsif(eeprom_addr_count=5)then eeprom_dram_op<=0; eeprom_op_done<='1'; --signal were done else eeprom_dram_op<=2; --haha this is READ DUDE!!!!!! eeprom_address(31 downto 16)<=X"01FF"; if(eeprom16k='1')then eeprom_address(15 downto 0)<=(X"C000" + ("00000" & eeprom_dat(7 downto 0) & "000") + ("00000000000" & eeprom_addr_count & "0")) AND X"C3FF"; else eeprom_address(15 downto 0)<=(X"C000" + ("00000" & eeprom_dat(7 downto 0) & "000") + ("00000000000" & eeprom_addr_count & "0")) AND X"C1FF"; end if; if(DRAM_STATE=45)then --grab data eeprom_dat_out<=eeprom_dat_out(64-16 downto 0) & DQ; eeprom_addr_count<=eeprom_addr_count + 1; end if; end if; end if; if(last_eeprom_state2=30)then --WRITE if(eeprom_addr_count=4)then eeprom_dram_op<=0; eeprom_addr_count<=eeprom_addr_count + 1; elsif(eeprom_addr_count=5)then eeprom_dram_op<=0; eeprom_op_done<='1'; --signal were done else eeprom_dram_op<=1; --yaya write! eeprom_address(31 downto 16)<=X"01FF"; if(eeprom16k='1')then eeprom_address(15 downto 0)<=(X"C000" + ("00000" & eeprom_dat(71 downto 64) & "000") + ("00000000000" & eeprom_addr_count & "0")) AND X"C3FF"; else eeprom_address(15 downto 0)<=(X"C000" + ("00000" & eeprom_dat(71 downto 64) & "000") + ("00000000000" & eeprom_addr_count & "0")) AND X"C1FF"; end if; if(DRAM_STATE=40)then EEPROM_data_in<=eeprom_dat_out(63 downto 48); end if; if(DRAM_STATE=45)then --increment count and shift register here eeprom_addr_count<=eeprom_addr_count + 1; eeprom_dat_out(63 downto 16)<=eeprom_dat_out(47 downto 0); end if; end if; end if; if(last_eeprom_state2=0)then eeprom_op_done<='0'; eeprom_dram_op<=0; eeprom_addr_count<=(others=>'0'); eeprom_dat_out(63 downto 0)<=eeprom_dat(63 downto 0); end if; --got push it thru some FF to take care of metastbility from that other clock domain AGAIN , when does it ever STOP??!! last_eeprom_state2:=last_eeprom_state; last_EEPROM_STATE:=EEPROM_STATE; --dram refresh stuff --maintain a counter of last time since read/write activity if((last_read/=last_read2) or (last_write/=last_write2))then read_counter<=0; end if; if(read_counter<=250)then read_counter<=read_counter+1; end if; --when no R/W activity then refresh very often ,when n64 R/W then back off for some time to not interfere with them if(refresh_count>=0)then --how fast to refresh if(DRAM_STATE=11)then refresh_dram<='0'; refresh_count<=0; --careful careful now, if you disable refresh too long then when uploading data will cause previous bits to flip elsif(read_counter>=36)then --dont refresh unless long period of read inactivity refresh_dram<='1'; end if; else refresh_count<=refresh_count+1; end if; --------n64 related stuff-------------------------------------------- if(DRAM_STATE=33)then if(sram_flag_write='1' or n64_dram_op=1)then n64_address<=n64_address+2; sram_flag_write<='0'; end if; n64_dram_op<=0; --reset op when its gotten past state 32 end if; --------OK, here the game plan fellas. We dont want to have to RUN RUN through the dram states to get some data to the n64 when read goes low instead --------we want the data to be ready way before. So at each address change go ahead and issue a read command. --------That will be ALE_x stuff and when read goes high which signals address increment if(n64_cold_reset='1')then if(last_read='0' and last_read2='1')then --rising edge if ( (n64_address(31 downto 16) < X"1800") ) then --beyond 64MB mark n64_address<=n64_address+2; n64_dram_op<=2; end if; elsif(last_write='1' and last_write2='0')then --falling edge n64_dram_op<=1; elsif(last_write='0' and last_write2='1')then --rising edge --sram_flag_write<='1'; elsif(last_alel='1' and last_alel2='0')then --falling edge n64_address<=start_n64_address; --transfer complete address after alel goes low n64_dram_op<=2; end if; else n64_dram_op<=0; sram_flag_write<='0'; end if; --MAP SRAM to last 64k of memory if ( (n64_address(31 downto 16) >= X"0800") and (n64_address(31 downto 16) <= X"0801") ) then n64_address(31 downto 16)<=X"01FF"; --sram at end of dram end if; --run read/write signal thru 2 FF to avoid metastability --better to just use it as a clock input to set a flag last_read:=last_read2; last_read2:=read; last_write:=last_write2; last_write2:=write; -- last_write2:='1'; last_alel:=last_alel2; last_alel2:=alel_1; --ALE_L; if(write='0')then N64_data_in<=AD; end if; end if; --grab Dram DQ data on rising edge to be politically correct if(CLK2X_g'Event and CLK2X_g='0')then --data snatcher for FX2 --(remember the DRAM_STATE at same clock edge as state changer is one clock behind) --(when opposite clock edge DRAM_STATE is the actaul state) if(NEXT_STATE=7)then --grab the DRAM data at the correct CAS latency --if(DRAM_STATE=7)then --grab the DRAM data at the correct CAS latency if(pc_dram_op=2)then temp_FX2_data_out<=DQ; end if; end if; --data snatcher for n64 if(NEXT_STATE=36)then --grab the DRAM data when appropriate --if(DRAM_STATE=36)then --grab the DRAM data when appropriate if ( (n64_address(31 downto 16) >= X"1800") ) then --beyond 64MB mark --seems some carts access ROM from 0x1FD0 0000 to 0x7FFF FFFF Cartridge Domain 1 Address 3 --some games try to access this area (hello castlevania) --probably some lame attempt to check if some DMA is finished --the value returned is basically the last data driven onto the BUS , the low 16 bits of the address N64_data_out<=n64_address(15 downto 0); else N64_data_out<=DQ; end if; end if; end if; end process; process(DRAM_STATE) begin NEXT_STATE<=0; clk_delay<=0; --# of cycle to stall the state machine to observe the setup times of sdram RAS<='1'; CAS<='1'; WE<='1'; CS<='1'; DQ<=(others=>'Z'); AD<=(others=>'Z'); if(read='0')then AD<=N64_data_out; else AD<=(others=>'Z'); end if; ----state machine is driven by 60mhz clock (2x IFCLK from FX2) make sure to observe proper setup and hold times case(DRAM_STATE) is when 0=> if(n64_dram_op/=0)then --give n64 priority NEXT_STATE<=30; elsif(pc_dram_op/=0)then --read/write dram NEXT_STATE<=1; elsif(eeprom_dram_op/=0)then NEXT_STATE<=40; elsif(refresh_dram='1')then NEXT_STATE<=10; else NEXT_STATE<=0; end if; --ACTIVE to READ/WRITE 20ns --ACTIVE to ACTIVE 60ns --ACTIVE to precharge 44ns when 1=> --activate row CS<='0'; RAS<='0'; CAS<='1'; WE<='1'; A<=pc_address(22 downto 10); BA<=pc_address(24 downto 23); NEXT_STATE<=2; when 2=> clk_delay<=0; NEXT_STATE<=3; when 3=> --read or write CS<='0'; RAS<='1'; CAS<='0'; A(10)<='0'; --disable auto precharge A(8 downto 0)<=pc_address(9 downto 1); BA<=pc_address(24 downto 23); if(pc_dram_op=1)then --write WE<='0'; DQ<=FX2_data_in; elsif(pc_dram_op=2)then WE<='1'; DQ<=(others=>'Z'); end if; NEXT_STATE<=4; when 4=> CS<='0'; --precharge to terminate read/write RAS<='0'; CAS<='1'; WE<='0'; A(10)<='1'; --all banks -- CS<='0'; --go ahead and burst terminate since we only want ONE WORD and DQM is tied low -- RAS<='1'; -- CAS<='1'; -- WE<='0'; NEXT_STATE<=5; when 5=> NEXT_STATE<=6; when 6=> --data is valid here (CAS latency=xxx) NEXT_STATE<=7; --------state machine exit-------------- when 7=> --data is valid here (CAS latency=xxx) NEXT_STATE<=0; --------REFRESH stuff------------------- --AUTO Refresh period 66ns when 10=> NEXT_STATE<=11; when 11=> --auto refresh CS<='0'; RAS<='0'; CAS<='0'; WE<='1'; NEXT_STATE<=12; when 12=> clk_delay<=2; NEXT_STATE<=13; when 13=> NEXT_STATE<=0; --------N64 read or write -------------- when 30=> --activate CS<='0'; RAS<='0'; CAS<='1'; WE<='1'; A<=n64_address(22 downto 10); BA<=n64_address(24 downto 23); NEXT_STATE<=31; when 31=> clk_delay<=0; NEXT_STATE<=32; when 32=> --read or write CS<='0'; RAS<='1'; CAS<='0'; A(10)<='0'; --disable auto precharge A(8 downto 0)<=n64_address(9 downto 1); BA<=n64_address(24 downto 23); if(n64_dram_op=1)then --write WE<='0'; DQ<=N64_data_in; elsif(n64_dram_op=2)then --read WE<='1'; DQ<=(others=>'Z'); end if; NEXT_STATE<=33; when 33=> CS<='0'; --precharge RAS<='0'; CAS<='1'; WE<='0'; A(10)<='1'; --all banks NEXT_STATE<=34; when 34=> NEXT_STATE<=35; when 35=> --data valid NEXT_STATE<=36; when 36=> clk_delay<=0; NEXT_STATE<=0; --------EEPROM read or write -------------- when 40=> --activate CS<='0'; RAS<='0'; CAS<='1'; WE<='1'; A<=eeprom_address(22 downto 10); BA<=eeprom_address(24 downto 23); NEXT_STATE<=41; when 41=> clk_delay<=0; NEXT_STATE<=42; when 42=> --read or write CS<='0'; RAS<='1'; CAS<='0'; A(10)<='0'; --disable auto precharge A(8 downto 0)<=eeprom_address(9 downto 1); BA<=eeprom_address(24 downto 23); if(eeprom_dram_op=1)then --write WE<='0'; DQ<=EEPROM_data_in; elsif(eeprom_dram_op=2)then --read WE<='1'; DQ<=(others=>'Z'); end if; NEXT_STATE<=43; when 43=> CS<='0'; --precharge RAS<='0'; CAS<='1'; WE<='0'; A(10)<='1'; --all banks NEXT_STATE<=44; when 44=> NEXT_STATE<=45; when 45=> --data valid NEXT_STATE<=46; when 46=> clk_delay<=0; NEXT_STATE<=0; when others => NEXT_STATE<=0; end case; end process; --EEprom stuff handling process;) process(serial_clk) variable bith : integer range 0 to 7:=0; variable bitl : integer range 0 to 7:=0; variable change_count : integer range 0 to 3; variable last_bit : std_logic:='0'; variable bits_recv : integer range 0 to 80:=0; variable eeprom_bit : std_logic:='1'; variable eeprom_op : integer range 0 to 3:=0; variable eeprom_send_count : integer range 0 to 65:=0; --add one for stop bit variable bit_length : integer range 0 to 8:=0; variable test_count : integer range 0 to 1000:=0; begin if(eeprom_bit='0')then eeprom<='0'; else eeprom<='Z'; end if; if(n64_cold_reset='0') then change_count:=0; bith:=0; bitl:=0; bits_recv:=0; eeprom_bit:='1'; EEPROM_STATE<=0; eeprom_op:=0; elsif(serial_clk'Event and serial_clk='1')then --we only sample and respond on the rising edge of the clock if(eeprom_op=0)then --if were in the middle of providing some response data then dont try to read bits --decode incoming bits if(eeprom='0')then if(last_bit='1')then if(bitl/=0)then if(bith>bitl)then --more high bits represent 1 eeprom_dat<=eeprom_dat(79 downto 0) & '1'; else eeprom_dat<=eeprom_dat(79 downto 0) & '0'; end if; bits_recv:=bits_recv+1; bitl:=0; --reset bit low at each falling edge of bit stream end if; end if; if(bitl<7)then bitl:=bitl+1; end if; bith:=0; else --incoming bit is high if(bith=7)then --end of transx change_count:=0; bitl:=0; if(bits_recv=8)then --check for STATUS req if(eeprom_dat(7 downto 0)=X"00")then --get status eeprom_op:=1; if(eeprom16k='1')then eeprom_dat(24 downto 0)<=X"00C000" & '1'; --16k eeprom else eeprom_dat(24 downto 0)<=X"008000" & '1'; --4k eeprom end if; end if; elsif(bits_recv=16)then --check for READ req if(eeprom_dat(15 downto 8)=X"04")then -- eeprom_dat(64 downto 0)<=X"AABBCCDD00112233" & '1'; eeprom_op:=2; end if; elsif(bits_recv=80)then --check for WRITE req if(eeprom_dat(79 downto 72)=X"05")then eeprom_op:=3; end if; end if; bits_recv:=0; --clear this so we dont check again else change_count:=1; bith:=bith+1; end if; end if; end if; last_bit:=eeprom; --EEPROM <-> PIF communication state machine --default override eeprom_bit:='1'; EEPROM_STATE<=0; case(EEPROM_STATE) is when 0=> eeprom_send_count:=0; bit_length:=0; if(eeprom_op=1)then --status EEPROM_STATE<=1; elsif(eeprom_op=2)then --read EEPROM_STATE<=20; elsif(eeprom_op=3)then --write EEPROM_STATE<=30; end if; when 1=> --send status if(eeprom_send_count=25)then eeprom_op:=0; EEPROM_STATE<=0; --exit elsif(eeprom_dat(24-eeprom_send_count)='0')then bit_length:=5; EEPROM_STATE<=2; else bit_length:=1; EEPROM_STATE<=4; end if; --00000011 ('0' in n64 speak) when 2=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=2; else bit_length:=1; --state 1 handles the other one EEPROM_STATE<=3; end if; when 3=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=3; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=1; end if; --00111111 ('1' in n64 speak) when 4=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=4; else bit_length:=5; --state 1 handles the other one EEPROM_STATE<=5; end if; when 5=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=5; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=1; end if; -------------------------------------- when 20=> --do read req eeprom_send_count:=0; if(eeprom_op_done='0')then --wait for 4 16bit words + 1 stop bit to be read EEPROM_STATE<=20; else EEPROM_STATE<=21; end if; when 21=> if(eeprom_send_count=65)then eeprom_op:=0; EEPROM_STATE<=0; --exit elsif(eeprom_dat_out(64-eeprom_send_count)='0')then bit_length:=5; EEPROM_STATE<=22; else bit_length:=1; EEPROM_STATE<=24; end if; --00000011 ('0' in n64 speak) when 22=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=22; else bit_length:=1; --state x handles the other one EEPROM_STATE<=23; end if; when 23=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=23; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=21; end if; --00111111 ('1' in n64 speak) when 24=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=24; else bit_length:=5; --state x handles the other one EEPROM_STATE<=25; end if; when 25=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=25; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=21; end if; -------------------------------------- when 30=> --do write req eeprom_send_count:=0; if(eeprom_op_done='0')then --wait for 4 16bit words to get stored EEPROM_STATE<=30; else EEPROM_STATE<=31; end if; when 31=> --send 8 bit '00000000' response to PIF that write was successful if(eeprom_send_count=9)then eeprom_op:=0; EEPROM_STATE<=0; --exit elsif(eeprom_send_count<8)then bit_length:=5; EEPROM_STATE<=32; else bit_length:=1; --transmit 1 'stop' bit EEPROM_STATE<=34; end if; --00000011 ('0' in n64 speak) when 32=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=32; else bit_length:=1; --state x handles the other one EEPROM_STATE<=33; end if; when 33=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=33; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=31; end if; --00111111 ('1' in n64 speak) when 34=> --transmit 0 eeprom_bit:='0'; if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=34; else bit_length:=5; --state x handles the other one EEPROM_STATE<=35; end if; when 35=> --transmit 1 if(bit_length>0)then bit_length:=bit_length-1; EEPROM_STATE<=35; else eeprom_send_count:=eeprom_send_count+1; EEPROM_STATE<=31; end if; when others=> EEPROM_STATE<=0; end case; end if; end process; end Behavioral;