Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21069 Discussions

Trouble interfacing FLASH pins to GPIO (retro game related)

Altera_Forum
Honored Contributor II
2,656 Views

Hey all, 

 

Just got an Altera DE1 dev board using the Cyclone II, and I'm working on a simple test that is literally just connecting the FLASH chip to the GPIO_0 bus. I'm not performing any logic, but the FLASH does have code I wrote to it using the DE Control panel, and I've verified my code is correct. 

 

This is a test to send a small test ROM file from the DE1 to the GPIO ports which are connected to a Super Nintendo cartridge. I've done similar tests with Xilinx CPLD before (data lines ran direct to system, but address and control lines ran to CPLD), but this is my first foray into sending all pins through a FPGA. 

 

My problem is that the game will not boot! I've double and triple checked my wiring, and that's good. Each pin on the SNES just connects to one of the corresponding GPIO pins, which is routed to the FLASH pins through the FPGA. I've never run data lines through a PLD before, so I don't know if there is something special that they need in contrast to a regular address line? Or is there something glaringly obvious that I'm missing? 

 

I've attached my code in hopes someone can help me out. 

 

Also, I've already added FL_CE_N into my pin assignments as I noticed that it was missing originally. 

 

library ieee;use ieee.std_logic_1164.all; entity mapper is port( FL_ADDR : out std_logic_vector(21 downto 0) ; FL_DQ : out std_logic_vector(7 downto 0) ; FL_CE_N : out std_logic; FL_OE_N : out std_logic; FL_RST_N : out std_logic; FL_WE_N : out std_logic; GPIO_0 : inout std_logic_vector(35 downto 0) ); end mapper; architecture arch of mapper is begin --CONTROL LINES FL_CE_N <= '0'; FL_OE_N <= '0'; FL_RST_N <= '1'; FL_WE_N <= '1'; --DATA LINES FL_DQ(7 downto 0) <= GPIO_0(21 downto 14); -- ADDRESS LINES FL_ADDR(17) <= GPIO_0(2); FL_ADDR(16) <= GPIO_0(24); FL_ADDR(15) <= GPIO_0(4); FL_ADDR(14) <= GPIO_0(29); FL_ADDR(13) <= GPIO_0(28); FL_ADDR(12) <= GPIO_0(5); FL_ADDR(11) <= GPIO_0(25); FL_ADDR(10) <= GPIO_0(23); FL_ADDR(9) <= GPIO_0(26); FL_ADDR(8) <= GPIO_0(27); FL_ADDR(7) <= GPIO_0(6); FL_ADDR(6) <= GPIO_0(7); FL_ADDR(5) <= GPIO_0(8); FL_ADDR(4) <= GPIO_0(9); FL_ADDR(3) <= GPIO_0(10); FL_ADDR(2) <= GPIO_0(11); FL_ADDR(1) <= GPIO_0(12); FL_ADDR(0) <= GPIO_0(13); end arch; 

 

Any ideas and help here would be greatly appreciated, thanks!
0 Kudos
17 Replies
Altera_Forum
Honored Contributor II
1,750 Views

I don't quite understand what you're trying to do here. You're doing read-only on the flash (FL_WE_N <= 1) and you're sending data from GPIO_0 to FL_DQ, which won't do anything because you're doing read-only. 

 

Also, why is GPIO_0 bidirectional? 

 

If you're trying to send something out of GPIO_0, GPIO_0 must be on the left hand side of an assignment somewhere.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

I don't quite understand what you're trying to do here. You're doing read-only on the flash (FL_WE_N <= 1) and you're sending data from GPIO_0 to FL_DQ, which won't do anything because you're doing read-only. 

 

Also, why is GPIO_0 bidirectional? 

 

If you're trying to send something out of GPIO_0, GPIO_0 must be on the left hand side of an assignment somewhere. 

--- Quote End ---  

 

 

That's a bit of what I was confused about. It had looked like in the datasheet for this dev board that GPIO 1 and 2 were both bidirectional, so I figured I needed to implement them as such? 

 

So if i'm understanding you properly, seeing as the FLASH is in read-only mode, it's pins (maybe aside from the control pins) should be set as INPUT in my port list, all driving the GPIO? 

 

So: 

 

library ieee; use ieee.std_logic_1164.all; entity mapper is port( FL_ADDR : in std_logic_vector(21 downto 0) ; FL_DQ : in std_logic_vector(7 downto 0) ; FL_CE_N : out std_logic; FL_OE_N : out std_logic; FL_RST_N : out std_logic; FL_WE_N : out std_logic; GPIO_0 : out std_logic_vector(35 downto 0) ); end mapper; architecture arch of mapper is begin --CONTROL LINES FL_CE_N <= '0'; FL_OE_N <= '0'; FL_RST_N <= '1'; FL_WE_N <= '1'; --DATA LINES GPIO_0(21 downto 14) <= FL_DQ(7 downto 0) ; -- ADDRESS LINES GPIO_0(2) <= FL_ADDR(17); GPIO_0(24) <= FL_ADDR(16); GPIO_0(4) <= FL_ADDR(15); GPIO_0(29) <= FL_ADDR(14); GPIO_0(28) <= FL_ADDR(13); GPIO_0(5) <= FL_ADDR(12); GPIO_0(25) <= FL_ADDR(11); GPIO_0(23) <= FL_ADDR(10); GPIO_0(26) <= FL_ADDR(9); GPIO_0(27) <= FL_ADDR(8); GPIO_0(6) <= FL_ADDR(7); GPIO_0(7) <= FL_ADDR(6); GPIO_0(8) <= FL_ADDR(5); GPIO_0(9) <= FL_ADDR(4); GPIO_0(10) <= FL_ADDR(3); GPIO_0(11) <= FL_ADDR(2); GPIO_0(12) <= FL_ADDR(1); GPIO_0(13) <= FL_ADDR(0); end arch;
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

I'm still not sure what you're trying to do. Are you retrieving data from the flash and wanting to send it out the GPIO? If that's the case, then no, FL_ADDR should still be an output because you're trying to access an address location on the flash. FL_DQ should be an input, as you have it in the new code, to read in data from the selected flash address. 

 

But now you're sending an address and data out the GPIO. Is this your intention? If so, then the only issue with the new code is the direction of FL_ADDR. But you also need additional logic to specify what FL_ADDR should be to access a location in the flash.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

I'm still not sure what you're trying to do. Are you retrieving data from the flash and wanting to send it out the GPIO? If that's the case, then no, FL_ADDR should still be an output because you're trying to access an address location on the flash. FL_DQ should be an input, as you have it in the new code, to read in data from the selected flash address. 

 

But now you're sending an address and data out the GPIO. Is this your intention? If so, then the only issue with the new code is the direction of FL_ADDR. But you also need additional logic to specify what FL_ADDR should be to access a location in the flash. 

--- Quote End ---  

 

 

I'm trying to read data off of the chip (in this case a test game), send it through the FPGA and into the GPIO pins, which then runs into a cartridge so that the SNES console can read it. Sorry if that wasn't clear to begin with. 

 

If I make FL_ADDR an output, how to get that to work with the GPIO if i also have that as an output? VHDL just gives me an error that way.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

You have to create a SIGNAL assignment for an additional signal in the design. 

 

SIGNAL FL_ADDR_TEMP (21 DOWNTO 0); 

 

Then let's say you want to access address location 0x24ffff (22 bit wide address though your code isn't using any of the upper bits for some reason): 

 

FL_ADDR <= x"24ffff"; 

FL_ADDR_TEMP <= FL_ADDR; 

 

Then the code you have would be: 

 

GPIO_0(2) <= FL_ADDR_TEMP(17); 

GPIO_0(24) <= FL_ADDR_TEMP(16); 

GPIO_0(4) <= FL_ADDR_TEMP(15); 

GPIO_0(29) <= FL_ADDR_TEMP(14); 

GPIO_0(28) <= FL_ADDR_TEMP(13); 

GPIO_0(5) <= FL_ADDR_TEMP(12); 

GPIO_0(25) <= FL_ADDR_TEMP(11); 

GPIO_0(23) <= FL_ADDR_TEMP(10); 

GPIO_0(26) <= FL_ADDR_TEMP(9); 

GPIO_0(27) <= FL_ADDR_TEMP(8); 

GPIO_0(6) <= FL_ADDR_TEMP(7); 

GPIO_0(7) <= FL_ADDR_TEMP(6); 

GPIO_0(8) <= FL_ADDR_TEMP(5); 

GPIO_0(9) <= FL_ADDR_TEMP(4); 

GPIO_0(10) <= FL_ADDR_TEMP(3); 

GPIO_0(11) <= FL_ADDR_TEMP(2); 

GPIO_0(12) <= FL_ADDR_TEMP(1); 

GPIO_0(13) <= FL_ADDR_TEMP(0);
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

You have to create a SIGNAL assignment for an additional signal in the design. 

 

SIGNAL FL_ADDR_TEMP (21 DOWNTO 0); 

 

Then let's say you want to access address location 0x24ffff (22 bit wide address though your code isn't using any of the upper bits for some reason): 

 

FL_ADDR <= x"24ffff"; 

FL_ADDR_TEMP <= FL_ADDR; 

 

Then the code you have would be: 

 

GPIO_0(2) <= FL_ADDR_TEMP(17); 

GPIO_0(24) <= FL_ADDR_TEMP(16); 

GPIO_0(4) <= FL_ADDR_TEMP(15); 

GPIO_0(29) <= FL_ADDR_TEMP(14); 

GPIO_0(28) <= FL_ADDR_TEMP(13); 

GPIO_0(5) <= FL_ADDR_TEMP(12); 

GPIO_0(25) <= FL_ADDR_TEMP(11); 

GPIO_0(23) <= FL_ADDR_TEMP(10); 

GPIO_0(26) <= FL_ADDR_TEMP(9); 

GPIO_0(27) <= FL_ADDR_TEMP(8); 

GPIO_0(6) <= FL_ADDR_TEMP(7); 

GPIO_0(7) <= FL_ADDR_TEMP(6); 

GPIO_0(8) <= FL_ADDR_TEMP(5); 

GPIO_0(9) <= FL_ADDR_TEMP(4); 

GPIO_0(10) <= FL_ADDR_TEMP(3); 

GPIO_0(11) <= FL_ADDR_TEMP(2); 

GPIO_0(12) <= FL_ADDR_TEMP(1); 

GPIO_0(13) <= FL_ADDR_TEMP(0); 

--- Quote End ---  

 

 

Ok, so I have re-written my code to hopefully make things more clear. I have changed the data bus behavior to work as "read-only" from the Flash chip, so that should make things simpler to implement. However, this still isn't working: 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity mapper_test is port( FL_ADDR : out std_logic_vector(21 downto 0); FL_DQ : in std_logic_vector(7 downto 0); FL_CE_N : out std_logic; FL_OE_N : out std_logic; FL_RST_N : out std_logic; FL_WE_N : out std_logic; -- LEDR : out std_logic_vector(9 downto 0); -- LEDG : out std_logic_vector(7 downto 0); -- SW : in std_logic_vector(2 downto 0); SNES_ADDR : in std_logic_vector(21 downto 0); -- SNES ADDRESS BUS SNES_DATA : out std_logic_vector(7 downto 0); -- SNES DATA BUS SNES_ROMSEL : in std_logic; -- /ROMSEL (CART PIN 49) SNES_RST : in std_logic; -- CART RESET SNES_VCC : in std_logic; -- CART VCC SNES_RD : in std_logic -- SNES /RD ); end mapper_test; architecture arch of mapper_test is begin --FLASH CONTROL PINS FL_CE_N <= SNES_ROMSEL; -- INPUT SNES /ROMSEL TO OUTPUT FLASH /CE FL_OE_N <= SNES_RD; -- INPUT SNES /RD TO OUTPUT FLASH /OE FL_RST_N <= '1'; -- KEEP FLASH /RST HIGH FL_WE_N <= '1'; -- KEEP FLASH /WE HIGH --FLASH DATA PINS SNES_DATA(7 downto 0) <= FL_DQ(7 downto 0); -- INPUT FLASH DATA BUS (7:0) TO OUTPUT SNES DATA BUS (7:0) FOR READ MODE --ADDRESS PINS FL_ADDR(14 downto 0) <= SNES_ADDR(14 downto 0); -- INPUT SNES ADDRESS (14:0) TO OUTPUT FLASH ADDRESS (14:0) FL_ADDR(20 downto 15) <= SNES_ADDR(21 downto 16); -- LOROM CONFIG ---> INPUT SNES ADDRESS (21:16) TO OUTPUT FLASH ADDRESS (20:15) FL_ADDR(21) <= '0'; -- KEEP FLASH(21) LOW FOR 2MBYTE ONLY end arch; 

 

Any ideas of what else it could be? I figure it still has to be with the data bus, but I don't know how else to write it.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

Anyone able to help with this?

0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

You have SNES_RST as an input to the FPGA and you're not doing anything with it. Should this be an output to the cart and set low (assuming it's active high)? 

 

What does SNES_ADDR(15) do? 

 

And what actually sets SNES_ADDR on your board/cart? Is there software somewhere else that does this?
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

You have SNES_RST as an input to the FPGA and you're not doing anything with it. Should this be an output to the cart and set low (assuming it's active high)? 

 

What does SNES_ADDR(15) do? 

 

And what actually sets SNES_ADDR on your board/cart? Is there software somewhere else that does this? 

--- Quote End ---  

 

 

The RST line I was trying with different code versions, to try and use it as a output_enable on the SNES lines. It didn't make a difference, so I commented it out (not shown in the code I pasted, my mistake). 

 

SNES_ADDR(15) is a variable address that is only used (for the most part) when a game is accessed via HIROM mode. My test game is not HIROM, so A15 is not used. This instead routes FLASH pins A15-A21 to SNES pins A16-A22, which is needed for my test game to work. This also answers your last part, this address information is handled by the software in the ROM file.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

This instead routes FLASH pins A15-A21 to SNES pins A16-A22, which is needed for my test game to work. This also answers your last part, this address information is handled by the software in the ROM file. 

--- Quote End ---  

 

 

Your code uses flash address pins A15-20, not 21 (21 is pulled low) and SNES address A16-21 (you don't have addr 22 on the SNES side). Minor, but could this be the issue? 

 

You could also have an IF assignment on SNES_ADDR(15) to route the address pins appropriately depending on whether it's high or low.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

The HIROM mode isn't the concern here. I know that works, but you're right in the future I could add an IF on A15. The system does have an A22 but it's not needed for this implementation. I don't think we need to delve into that more right now as it's not important to my original problem. 

 

My concern is just getting data actually read out to the console from the flash.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

OK, so what's the behavior right now? What's not working correctly? Have you thought about adding SignalTap to verify functionality or performing a simulation? Your code looks fine.

0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

The test game won't boot onto the console. When I tie the LEDs to the FL_DQ lines I don't see any indication that they're going hi or low. 

 

I haven't tried signaltap or sims yet, no. I've done this sort of thing with CPLD chips before with no trouble, but only controlling address and control pins - never with data pins. So that's why I'm hung up. It looks like it SHOULD work, but it doesn't. 

 

Any chance I need to things to high Z until the console boots? I tried that with using SNES_RST as an enable on all the FL pins but that didn't seem to do anything different either...
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

Well, then we have to start getting into I/O related stuff. What I/O standards have you set in the Pin Planner? What voltage are you using? Is anything working correctly at all?

0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

Fixed it. 

 

Didn't have the Data pins set to 'Z' when not being accessed. 

 

SNES_DATA <= FL_DQ when (SNES_ROMSEL = '0') else "ZZZZZZZZ"; 

 

That works properly.
0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

Well, that explains why you had GPIO_0 as inout in the original code! Did you change SNES_DATA to inout? I'm guessing yes since you can't make an assignment to a port if it's an input.

0 Kudos
Altera_Forum
Honored Contributor II
1,750 Views

 

--- Quote Start ---  

Well, that explains why you had GPIO_0 as inout in the original code! Did you change SNES_DATA to inout? I'm guessing yes since you can't make an assignment to a port if it's an input. 

--- Quote End ---  

 

 

No it's set as an Out only. I don't need to read from it right now, so implementation as an Out seemed easier anyways.
0 Kudos
Reply