james1095

Asteroids

Recommended Posts

Having been distracted by other projects for a while, I'm back to playing with FPGAs. I'm trying to port Asteroids Deluxe from FPGA Arcade http://www.fpgaarcade.com/ast_main.htm to run on the Papilio Pro. Instead of the rasterizer he used, I want to output the X, Y and Z values directly to a DAC to drive a real vector display. I've found some code to do just that from here http://spritesmods.com/?art=bwidow_fpga but first I need to get the base code working on the LX9.

 

I've modified the block RAM section of asteroids_rams.vhd to use the same structure I used when I successfully ported Pacman to the LX9:

 

 r1 : component RAMB16_S9
    port map (      
        do   => DOUT(7 downto 4),
      dop  => open,
      addr => ADDR(9 downto 0),
      clk  => CLK,
      di   => DIN(7 downto 4),
      dip  => "0",
      en   => '1',
      ssr  => '0',
      we   => we        
      );


  r0 : component RAMB16_S9
    port map (    
        do   => DOUT(3 downto 0),
      dop  => open,
      addr => ADDR(9 downto 0),
      clk  => CLK,
      di   => DIN(3 downto 0),
      dip  => "0",
      en   => '1',
      ssr  => '0',
      we   => we        
        
      );

 

 

Unfortunately when I try to compile I get errors for both block RAMs "Line 68: <ramb16_s9> is not declared."

 

This has GOT to be something simple, but I think I've stared at it too long to see whatever the issue is. Can someone offer any tips?

Share this post


Link to post
Share on other sites

I think that error usually means that you are trying to instantiate something without ever defining the component anywhere. Since the ramb16_s9 component is a xilinx primitive it should already be defined.

 

I would double check the type of chip that you have selected for your project and make sure that the libraries you are using at the top of the file match up with the other projects.

 

Worst case scenario just zip up your project and post it here so we can take a look.

 

Jack.

Share this post


Link to post
Share on other sites

Jack's correct, you're missing an include. From memory it's something like Unisim.vcomponents.all

I've also found that component declarations are completely redundant in a homogenous VHDL project if you instantiate your modules using "entity work.modulename"

Share this post


Link to post
Share on other sites

Good catch, yeah adding Unisim.vcomponents.all got me past the error I was running into, thanks!

 

Now I need to figure something else out, as the RAMs in the original Asteroids implementation are only 4 bits wide and I get mismatch errors. The code seems rather convoluted and takes a while to digest. Getting it going on the Spartan3 would probably be easier, but the 500k and 700k boards I have lack sufficient BRAM and the Spartan3 series in general looks like it's being phased out by Xilinx.

Share this post


Link to post
Share on other sites

You can still use all the Spartan3 RAMB primitives on the Spartan6 and XST will automagically translate them. Try using RAMB16_S4 if you say you have 4 bit RAMBs

Share this post


Link to post
Share on other sites

Yeah I tried that and got an error that I assumed was due to a bus width mismatch but maybe I'm barking up the wrong tree.

 

Here's what I have in asteroids_ram.vhd:

 

library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_arith.all;
  use ieee.std_logic_unsigned.all;
 
library UNISIM;
  use UNISIM.Vcomponents.all;


use work.pkg_asteroids_xilinx_prims.all;
use work.pkg_asteroids.all;

entity ASTEROIDS_RAM is
  port (
  ADDR   : in  std_logic_vector(9 downto 0);
  DIN    : in  std_logic_vector(7 downto 0);
  DOUT   : out std_logic_vector(7 downto 0);
  RW_L   : in  std_logic;
  CS_L   : in  std_logic; -- used for write enable gate only
  ENA    : in  std_logic; -- ditto
  CLK    : in  std_logic
  );
end;

architecture RTL of ASTEROIDS_RAM is

  signal we : std_logic;

begin
  r1 : component RAMB16_S4
    port map (      
        do   => DOUT(7 downto 4),
      addr => ADDR(9 downto 0),
      clk  => CLK,
      di   => DIN(7 downto 4),
      en   => '1',
      ssr  => '0',
      we   => we        
      );


  r0 : component RAMB16_S4
    port map (    
        do   => DOUT(3 downto 0),
      addr => ADDR(9 downto 0),
      clk  => CLK,
      di   => DIN(3 downto 0),
      en   => '1',
      ssr  => '0',
      we   => we        
        
      );

  p_we : process(RW_L, CS_L, ENA)
  begin
    we <= (not CS_L) and (not RW_L) and ENA;
  end process;

end architecture RTL;

 

 

 

And here are the errors that I get:

 

ERROR:HDLCompiler:1566 - "C:\Xilinx\Projects\asteroids_rel003\source\asteroids_ram.vhd" Line 75: Expression has 10 elements ; formal addr expects 12
ERROR:HDLCompiler:432 - "N:/P.28xd/rtf/devlib/vhdl/src/unisims/unisim_VCOMP.vhd" Line 28412: Formal <addr> has no actual or default value.

 

The original unmodified code is available from fpgaarcade.com if anyone would like to see what I started with.

Share this post


Link to post
Share on other sites

Hmm... .that is as clear as day right there in the error message, in file C:\Xilinx\Projects\asteroids_rel003\source\asteroids_ram.vhd you have an address bus size mismatch with formal addr which has 10 elements (0..9) but most likely you're connecting it to something that supplies 12 address lines.

 

The problem is that the error message points to line 75 in asteroids_ram.vhd but the code you posted above doesn't have much more than 50 lines so most likely there is more in that file or you're looking at the wrong source file. I'd double check your addr line connections and make sure you're matching the standard_logic_vector sizes properly.

Share this post


Link to post
Share on other sites

There are a bunch of comments at the top which I didn't post here as I didn't consider them relevant to the discussion at hand. In retrospect it would have made it clearer which line was which. Yeah I realize there's a mismatch in the bus width as I mentioned earlier, I'm just not entirely sure how to best fix it. I suppose I can create another signal in the rams file and assign it to the relevant portion of the bus.

 

At this point it may be time for me to go through the VHDL tutorial again. A few weeks of not playing with this stuff and it's shocking how much I've forgotten already.

Share this post


Link to post
Share on other sites

Easy really, in your RAMB assignments you'd go

addr(11 downto 10) => "00",

addr(9 downto 0) => ADDR,

done!

Of course I fail to see why the need for two 4 bit data bus RAMB instead of just using one 8 bit (strictly speaking 9 bit RAMB16_S9) saving one RAMB

Share this post


Link to post
Share on other sites

Oh! I had tried part of that, but hadn't put addr(11 downto 10) => "00" to deal with the extra bits so it was still complaining.

 

 

Well it gets further! Now I realized that the ROM files are using RAMB4_S2 which doesn't work on the Spartan6. I think this should be reasonably straightforward but I'll have to wait until after work to dig into this more. Looks like romgen can spit out RAM4 or RAM16 so that appears to be the obvious place to start.

 

Slowly getting there and having fun in the process. If only this stuff came to me as naturally as hardware!

Share this post


Link to post
Share on other sites

Well I dropped in the latest version of romgen and I was able to build new ROM VHDLs that use RAMB16_S9 and these seem to work. Now it's complaining about the clocks so it looks like the next step is to trim out the clock management currently there and use the DCM generator to get all the required clocks from the 32MHz oscillator. Looks like there is some clock logic for driving the external SRAM for the rasterizer that I can rip out as well. Getting closer! Then it's on to patching in the delta-sigma DACs from Spritesmods.

 

If I can manage to get this to work, the next step is to look at the feasibility of getting the original Asteroids code to run in place of Asteroids Deluxe. The hardware is very similar, except Deluxe adds an EAROM for storing high scores, and replaces the discrete analog sound circuits with a POKEY. Unfortunately the POKEY sounds relatively flat compared to the analog effects which were *perfect*. It would be relatively easy to implement the analog portions of the sound circuit on a separate board. It could probably be implemented digitally in the FPGA but DSP stuff is outside my skillset. Asteroids is such a great game, and due to it's superb exploitation of the capabilities of a CRT vector monitor, it's a game that just can't be emulated properly using any other display technology. There is nothing else out there capable of producing those blinding white shots on a dark black background.

Share this post


Link to post
Share on other sites

Of course I fail to see why the need for two 4 bit data bus RAMB instead of just using one 8 bit (strictly speaking 9 bit RAMB16_S9) saving one RAMB

 

Thats because the original circuit uses two 4 bit ram chips

 

Some of the people who create these FPGA versions want them to be identical to the original board (such as this), whereas others (include me in this block) are happy to make it functionally identical - what difference is it going to make to playing the game if it uses one 8 bit ram block instead of two 4 bit ram blocks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now