Jump to content
IGNORED

TMS9900 CPU core creation attempt


speccery

Recommended Posts

Ah, well, using SRAM then you do have a lot of room to improve the memory access. :-)

 

I'll have to give the Xilinx SDRAM controller a try. It looked very confusing and complicated the first time I started messing with SDRAM, so I rolled my own controller based on a simpler design I found online (hamster works). The problem with the burst mode and 64-bit transfers is that the 9900 does not really have that kind of access pattern, and you need a memory controller and cache to even begin to take advantage of any memory access over 16-bits. For completely random access, the read access time is still about 70ns on even the fastest SDRAM.

 

The configuration options for the Spartan 6 memory controller block (MCB) seemed daunting at first, and I could not find any VHDL examples, only one example with Verilog. But at the end of the day with the Pipistrello board it was relatively easy to setup, as the Micron memory chip was one of the supported targets on the ISE 14.7.

 

You are absolutely right about the burst mode and the 9900, it is not a good fit. Like you say at least a small cache would be necessary. Also the Xilinx MCB is not really byte or word or even 64-bit word oriented, since it has FIFOs both for writing and reading. Great for performance, but complex for simple setups. In the only design I have used it in (the TI-99/4A 64Meg memory expansion) I think I configured it for 32-bit access width and only wrote single words to and from the FIFOs. Basically for writes you first push your data to the write fifo, provide an address and a count, and off it goes. For reads I used a separate port (the MCB is a big piece of machinery with 6 access ports if I remember correctly) and in that port I needed to first write read address and count, then it goes off and does its thing, and while doing it one can monitor when the read FIFO starts to have data in it. So it is designed for asynchronous accesses. Should be a good fit for cache line reads and writes.

 

Below is the component declaration as I use it - this works (below not shown are the state machines driving reads and writes, something like 300 lines of code):

	-- LPDDR controller declaration
	component erik_lpddr
	 generic(
		 C3_P0_MASK_SIZE           : integer := 4;
		 C3_P0_DATA_PORT_SIZE      : integer := 32;
		 C3_P1_MASK_SIZE           : integer := 4;
		 C3_P1_DATA_PORT_SIZE      : integer := 32;
		 C3_MEMCLK_PERIOD          : integer := 5000;
		 C3_RST_ACT_LOW            : integer := 0;
		 C3_INPUT_CLK_TYPE         : string := "SINGLE_ENDED";
		 C3_CALIB_SOFT_IP          : string := "TRUE";
		 C3_SIMULATION             : string := "FALSE";
		 DEBUG_EN                  : integer := 0;
		 C3_MEM_ADDR_ORDER         : string := "ROW_BANK_COLUMN";
		 C3_NUM_DQ_PINS            : integer := 16;
		 C3_MEM_ADDR_WIDTH         : integer := 13;
		 C3_MEM_BANKADDR_WIDTH     : integer := 2
	);
		 port (
		mcb3_dram_dq                            : inout  std_logic_vector(C3_NUM_DQ_PINS-1 downto 0);
		mcb3_dram_a                             : out std_logic_vector(C3_MEM_ADDR_WIDTH-1 downto 0);
		mcb3_dram_ba                            : out std_logic_vector(C3_MEM_BANKADDR_WIDTH-1 downto 0);
		mcb3_dram_cke                           : out std_logic;
		mcb3_dram_ras_n                         : out std_logic;
		mcb3_dram_cas_n                         : out std_logic;
		mcb3_dram_we_n                          : out std_logic;
		mcb3_dram_dm                            : out std_logic;
		mcb3_dram_udqs                          : inout  std_logic;
		mcb3_rzq                                : inout  std_logic;
		mcb3_dram_udm                           : out std_logic;
		c3_sys_clk                              : in  std_logic;
		c3_sys_rst_n                            : in  std_logic;
		c3_calib_done                           : out std_logic;
		c3_clk0                                 : out std_logic;
		c3_rst0                                 : out std_logic;
		mcb3_dram_dqs                           : inout  std_logic;
		mcb3_dram_ck                            : out std_logic;
		mcb3_dram_ck_n                          : out std_logic;
		-- Below is the first R/W port to LPDDR memory
		c3_p0_cmd_clk                           : in std_logic;
		c3_p0_cmd_en                            : in std_logic;
		c3_p0_cmd_instr                         : in std_logic_vector(2 downto 0);
		c3_p0_cmd_bl                            : in std_logic_vector(5 downto 0);
		c3_p0_cmd_byte_addr                     : in std_logic_vector(29 downto 0);
		c3_p0_cmd_empty                         : out std_logic;
		c3_p0_cmd_full                          : out std_logic;
		c3_p0_wr_clk                            : in std_logic;
		c3_p0_wr_en                             : in std_logic;
		c3_p0_wr_mask                           : in std_logic_vector(C3_P0_MASK_SIZE - 1 downto 0);
		c3_p0_wr_data                           : in std_logic_vector(C3_P0_DATA_PORT_SIZE - 1 downto 0);
		c3_p0_wr_full                           : out std_logic;
		c3_p0_wr_error                          : out std_logic;
		c3_p0_wr_count                          : out std_logic_vector(6 downto 0);
		c3_p0_wr_underrun                       : out std_logic;
		c3_p0_wr_empty									 : out std_logic;
		c3_p0_rd_clk                            : in std_logic;
		c3_p0_rd_en                             : in std_logic;
		c3_p0_rd_data                           : out std_logic_vector(C3_P0_DATA_PORT_SIZE - 1 downto 0);
		c3_p0_rd_full                           : out std_logic;
		c3_p0_rd_empty                          : out std_logic;
		c3_p0_rd_count                          : out std_logic_vector(6 downto 0);
		c3_p0_rd_overflow                       : out std_logic;
		c3_p0_rd_error                          : out std_logic;
		-- Below is the second R/W port to LPDDR memory
		c3_p1_cmd_clk                           : in std_logic;
		c3_p1_cmd_en                            : in std_logic;
		c3_p1_cmd_instr                         : in std_logic_vector(2 downto 0);
		c3_p1_cmd_bl                            : in std_logic_vector(5 downto 0);
		c3_p1_cmd_byte_addr                     : in std_logic_vector(29 downto 0);
		c3_p1_cmd_empty                         : out std_logic;
		c3_p1_cmd_full                          : out std_logic;
		c3_p1_wr_clk                            : in std_logic;
		c3_p1_wr_en                             : in std_logic;
		c3_p1_wr_mask                           : in std_logic_vector(C3_P1_MASK_SIZE - 1 downto 0);
		c3_p1_wr_data                           : in std_logic_vector(C3_P1_DATA_PORT_SIZE - 1 downto 0);
		c3_p1_wr_full                           : out std_logic;
		c3_p1_wr_empty                          : out std_logic;
		c3_p1_wr_count                          : out std_logic_vector(6 downto 0);
		c3_p1_wr_underrun                       : out std_logic;
		c3_p1_wr_error                          : out std_logic;
		c3_p1_rd_clk                            : in std_logic;
		c3_p1_rd_en                             : in std_logic;
		c3_p1_rd_data                           : out std_logic_vector(C3_P1_DATA_PORT_SIZE - 1 downto 0);
		c3_p1_rd_full                           : out std_logic;
		c3_p1_rd_empty                          : out std_logic;
		c3_p1_rd_count                          : out std_logic_vector(6 downto 0);
		c3_p1_rd_overflow                       : out std_logic;
		c3_p1_rd_error                          : out std_logic
	);


	end component;

Link to comment
Share on other sites

Wow, that is a big interface! Seems like it would waste more resources than it is worth. But, constant access and caching is the only way modern systems get performance out of SDRAM. I like to just stick to SRAM. :-)

I do have a simple SDRAM controller if you want something smaller and easier to use:

entity sdram_simple is
   port(
      -- Host side
      clk_100m0_i    : in std_logic;            -- Master clock
      reset_i        : in std_logic := '0';     -- Reset, active high
      refresh_i      : in std_logic := '0';     -- Initiate a refresh cycle, active high
      rw_i           : in std_logic := '0';     -- Initiate a read or write operation, active high
      we_i           : in std_logic := '0';     -- Write enable, active low
      addr_i         : in std_logic_vector(23 downto 0) := (others => '0');   -- Address from host to SDRAM
      data_i         : in std_logic_vector(15 downto 0) := (others => '0');   -- Data from host to SDRAM
      ub_i           : in std_logic;            -- Data upper byte enable, active low
      lb_i           : in std_logic;            -- Data lower byte enable, active low
      ready_o        : out std_logic := '0';    -- Set to '1' when the memory is ready
      done_o         : out std_logic := '0';    -- Read, write, or refresh, operation is done
      data_o         : out std_logic_vector(15 downto 0);   -- Data from SDRAM to host
 
      -- SDRAM side
      sdCke_o        : out std_logic;           -- Clock-enable to SDRAM
      sdCe_bo        : out std_logic;           -- Chip-select to SDRAM
      sdRas_bo       : out std_logic;           -- SDRAM row address strobe
      sdCas_bo       : out std_logic;           -- SDRAM column address strobe
      sdWe_bo        : out std_logic;           -- SDRAM write enable
      sdBs_o         : out std_logic_vector(1 downto 0);    -- SDRAM bank address
      sdAddr_o       : out std_logic_vector(12 downto 0);   -- SDRAM row/column address
      sdData_io      : inout std_logic_vector(15 downto 0); -- Data to/from SDRAM
      sdDqmh_o       : out std_logic;           -- Enable upper-byte of SDRAM databus if true
      sdDqml_o       : out std_logic            -- Enable lower-byte of SDRAM databus if true
   );
end entity;

16-bit data path with byte enables, and the FSM to drive it is very simple. It was designed for a Winbond W9812G6JH-75, but the only thing that makes it specific is the startup sequence (which is probably very similar between SDRAMs).

  • Like 1
Link to comment
Share on other sites

16-bit data path with byte enables, and the FSM to drive it is very simple. It was designed for a Winbond W9812G6JH-75, but the only thing that makes it specific is the startup sequence (which is probably very similar between SDRAMs).

 

 

Thanks Matthew! I think I took a look at your design earlier on your site. At that time I did not have a Spartan 6 + SDRAM FPGA board to test, but now I do - although I have not even powered on that board yet and I acquired it probably 6 months ago...

 

Not sure if you noticed my other posting before the bulky SDRAM controller stuff - but I did get interrupts working on the CPU core! A nice small personal victory!

Link to comment
Share on other sites

Heh, my first FPGA board sat on a shelf from 2006 to 2011 before I started messing with it. ;-)

 

Yeah, I did miss that tiny post about the interrupts. :-) Nice progress!

 

My SDRAM controller is very small and should work fine on a Spartan 3 as well (a Spartan 6 is not required). It does *not* use any built-in memory controllers (I think the Spartan 6 has a dedicated memory controller that you can use). It might even fit in a CPLD...

  • Like 1
Link to comment
Share on other sites

Happy birthday by the way Speccery.

 

 

Thank you Sinphaltimus :)

The past year has been very eventful for me; perhaps I will elaborate at a later date. I do hope I am getting a little wiser and not only older... I don't think this coming year I'll be able to match the craziness of the previous year - but being a pretty spontaneous person who knows how it will go. One of nicest things of past year has to be my discovery of the TI community :thumbsup:

  • Like 4
Link to comment
Share on other sites

I realize I didn't post here anything about my latest project update at hackaday. Anyway there is an update about getting interrupts and multiply instruction working.

 

I do want to get this thing working with original TI ROMs, and I decided that the easiest way for me to find out where things go haywire is to add some kind of single step capability to the CPU core. What I want to do is to single step some instructions from the TI ROM and record the value of program counter and flags (ST register) for the first X instructions, and then compare those values to what happens in classic99. I've already modified classic99 and recorded the values for PC and ST registers for the first 100 000 instructions after reset. Now I need to modify the CPU core and interface logic to be able to capture those values from the FPGA CPU too. Then it should be a simple matter of comparing and finding out where it goes wrong...

  • Like 4
Link to comment
Share on other sites

... What I want to do is to single step some instructions from the TI ROM and record the value of program counter and flags (ST register) for the first X instructions, and then compare those values to what happens in classic99. ...

 

Would this be easier if you implemented the -HOLD and HOLDA on your CPU?

(I am guessing here, but it looks like it would help with a single step implementation)

  • Like 1
Link to comment
Share on other sites

 

Would this be easier if you implemented the -HOLD and HOLDA on your CPU?

(I am guessing here, but it looks like it would help with a single step implementation)

 

 

Those are already implemented :)

When I load ROMs and/or GROMs or communicate with the disk DSR, that is done using DMA access from the PC over USB.

 

Some more details:

There is a difference here between my TMS99105 CPU board and the FPGA soft core CPU in this regard: with the TMS99105 there is a carefully timed timeslot during which host memory accesses can occur in the beginning of each TMS99105 memory cycle, e.g. every 200ns the host can read or write the CPU's memory while the CPU is running at full speed. Hold is not asserted in this case. I take advantage of the time the multiplexed nature of the TMS99105 memory bus: when it is outputting the address, the first 40ns or something like that of each 200ns memory cycle are allocated for host accesses when needed. Thus while the TMS99105 side of the FPGA interface is acquiring address from the TMS99105, the SRAM side of the FPGA memory bus can perform host memory cycles.

 

With the FPGA soft core CPU things are running already at 100MHz and there is no specific guaranteed time the host could access the memory transparently to the CPU, so the host accesses use DMA cycles with HOLD and HOLDA. (I chose to use positive logic for all control signals, so they are active high - this can be wrapped with a small VHDL wrapper if TMS9900 signal polarities are preferred). The USB transfers are handled by what I call the "serloader state machine", so the read/write command packets from the host are converted into read/write requests, which are served by asserting HOLD and waiting for the FPGA CPU core to respond with HOLDA. The CPU checks for HOLD during each opcode fetch. I also special cased reset handling - during reset HOLD is also respected. That way the host can just keep reset active and read/write the TMS9900 memory to load ROMs, without having the CPU messing around with halfloaded ROMs.

Link to comment
Share on other sites

Okay, I got the single stepping working on the FPGA CPU and I can now record and compare the values of PC and ST registers. I modified my "memloader" PC program to support single stepping, and executed 10 000 instructions on the FPGA. This is actually very slow, due to the number of USB transactions needed. But I got the data.

 

The good news is that I found a difference: up to instruction number 2442 both the FPGA CPU and Classic99 execute identically. There are some flag differences, but they don't seem to matter. The instruction number 2442 is at address >0604, and it is an "X 9", i.e. execute the opcode computed to register 9. I never tested the X instruction... Perhaps it does not work - actually almost certainly it doesn't. That instruction is part of a routine starting from >05EA. It computes the opcode of LDCR instruction with a variable shift count - presumably because this is coming from GROM or from some table. So I need to check that.

 

After that things continue pretty much identically up to instruction 4328 (on classic99). There are only some differences due to classic99 CPU serving two interrupts, while for some reason the FPGA CPU does not serve any. Perhaps the LDCR instruction mentioned above does not get executed and the TMS9901 blocks interrupts from the VDP. Anyway instruction 4328 is "CB @>83E5,14" and the following jump instruction goes different ways, meaning on classic99 VDP is initialised differently than on my FPGA system, or something like that. So I think I have a smoking gun here, and need to do more detective work - but that has to wait until another day and more time.

  • Like 4
Link to comment
Share on other sites

The good news is that I found a difference: up to instruction number 2442 both the FPGA CPU and Classic99 execute identically. There are some flag differences, but they don't seem to matter.

 

You realise you contradict yourself with these two sentences, right? ;)

 

That there are flag differences means that some of instructions (in truth, it might only be one instruction) is/are not setting the status register flags properly, and that means the code is, at some point or another, going to take the wrong path on a jump instruction.

 

Tursi's Classic99 source gode would be an excellent resource for determining how to set the flags for each instruction.

 

In other news, inspired by your writings here and on Hackaday, I went ahead and bought an FPGA eval board. Looked high and low for the Papilio board but it appears that it's not for sale any more. Can't find stock anywhere. A shame because I like that board. In the end I settled on the Mojo Board; I have no idea whatsoever if the FPGA on it is powerful or not! However, it is used in one of the books I have bought, so that was a major selling point. :thumbsup:

 

I'm going down the Verilog route, though. At least initially. It doesn't shred my brain as badly as VHDL :D .

 

Happy hacking :thumbsup:

  • Like 2
Link to comment
Share on other sites

I too have been inspired by this thread and the other one as well. I've been itching to learn FPGA programming for a few years now, and interfacing to the TI seems like the perfect opportunity. JediMatt42 used the Mojo board for their TIPI prototype, so it does work! I ordered a miniSpartan6+ board, but it's been almost a month and it still hasn't arrived. I went with that one instead of the Mojo for the HDMI connector, SDRAM and microSDcard slot. Lots of possibilities there.

  • Like 2
Link to comment
Share on other sites

I too have been inspired by this thread and the other one as well. I've been itching to learn FPGA programming for a few years now, and interfacing to the TI seems like the perfect opportunity. JediMatt42 used the Mojo board for their TIPI prototype, so it does work! I ordered a miniSpartan6+ board, but it's been almost a month and it still hasn't arrived. I went with that one instead of the Mojo for the HDMI connector, SDRAM and microSDcard slot. Lots of possibilities there.

Yes, indeed. The mind boggles! I quite liked the Mojo because you can plonk expansion boards on it, just like an Arduino, so I bought the IO sheild at the same time. It also has an Arduino CPU on there that you can program with the Arduino IDE and make it interact with the FPGA. Neat. But they're all cool. That should keep me busy for a while learning how to make it do PWM and all manner of cool stuff!

 

I've found it impossible to get a feel for the capacity of these things; I guess if the TIPI is done with a Mojo then it's reasonably powerful. Could I make a CPU with it (assuming I had the skills?)

Link to comment
Share on other sites

You realise you contradict yourself with these two sentences, right? ;)

Yes I do :) I guess what I meant by that is that I've been looking through the instructions sequences with respect to flag behaviour, and checking whether the differences cause branches to go different directions. I have been hoping that I could avoid having to through each and every instruction carefully through in terms of flag behaviour but of course you are right and there is no avoiding that....

 

I actually fixed the X instruction, and now I've got interrupts so the behaviour is the same in that regard. While interrupts are nice to have, the single stepping actually means that execution is so slow that the CPU is only serving interrupts. I suppose I need to introduce proper trace buffers.

 

In other news, inspired by your writings here and on Hackaday, I went ahead and bought an FPGA eval board. Looked high and low for the Papilio board but it appears that it's not for sale any more. Can't find stock anywhere. A shame because I like that board. In the end I settled on the Mojo Board; I have no idea whatsoever if the FPGA on it is powerful or not! However, it is used in one of the books I have bought, so that was a major selling point. :thumbsup:

Welcome to the club! I think I also have a clone of the Mojo board. I haven't gotten around to testing it - I only realised my boards needs a firmware update for the AVR CPU, and that in turn means soldering some wires to test pads in order to connect the AVR programmer. My "mojo" has Spartan XC6SLX9 FPGA, so it is the same as on the Pepino I've used for development, although with "only" a 144 pin package.

 

I'm going down the Verilog route, though. At least initially. It doesn't shred my brain as badly as VHDL :D .

 

Happy hacking :thumbsup:

 

Thanks! VHDL is like ADA, and I never programmed in ADA, so I've given this a try. My main programming language is actually C++, and Verilog looks much closer to C so I've been temped too...

Link to comment
Share on other sites

I've found it impossible to get a feel for the capacity of these things; I guess if the TIPI is done with a Mojo then it's reasonably powerful. Could I make a CPU with it (assuming I had the skills?)

 

If your Mojo board has the Spartan 6 on it you can definitely do CPUs on it. :) Multiprocessors even. My project could fit at least another TMS9900 core on the same FPGA, but need to get the first one working properly yet ;)

Link to comment
Share on other sites

I think this is off-topic, but everyone else is talking about learning FPGAs, so I can't help it! ;-)

 

There are tons of affordable FPGA devboards available now. Here are some that I have picked up or looked at over the years:

 

1. Digilent Spartan 3E Starter (this is the board the F18A was initially developed on: http://store.digilentinc.com/spartan-3e-starter-board-limited-time/

Digilent makes good stuff and they have all kinds of boards in many ranges, lots of I/O boards, etc.

 

2. Of course the Gadget Factory: http://store.gadgetfactory.net/

The Papilio boards are nice and there are a lot of add-on boards for I/O and such.

 

3. Xess.com: http://www.xess.com/

Nice boards, I have the XuLa2 and it is a nice compact board with enough features and I/O for most tasks.

 

4. Scarab FPGA boards: https://www.scarabhardware.com/

The miniSpartan6+ is good for experimenting with HDMI, although it does not use any kind of HDMI input or output drivers or protection, so you need to be careful.

 

5. Numato boards: https://numato.com/products/fpga-boards/xilinx-spartan6/

They have some boards with nice features.

 

6. A guy making a list of FPGA boards: https://joelw.id.au/FPGA/CheapFPGADevelopmentBoards

 

All of my boards have Xilinx FPGAs on them. The other alternative is Altera. Xilinx offers their tools for free for the low-end FPGAs (all the stuff we can afford), and like anything I found that once I learned the tools I was less inclined to try the alternatives. I think Altera probably offers tools as well, but I don't know (they were also bought by Intel a little while ago).

 

As for VHDL vs Verilog, I wrote a post about that on my website back when I was doing the F18A: http://codehackcreate.com/archives/date/2011/02

 

Basically it comes down to preference because at the end of the day both languages do the same thing, and you can even mix Verilog and VHDL in the same project if you want. Verilog is too much like a "progamming" language, and from what I have read over the years can sometime do things you don't expect due to the nature of the syntax. I prefer VHDL, by the way.

 

I have a post about books too, see the link above to my website. I have a *lot* of FPGA books now, but the ones on my website are still the best I have found for learning and getting circuits working. Basically these two:

 

FPGA Prototyping by VHDL Examples: Xilinx Spartan-3 Version (available in a Verilog version too, well worth the money!)

https://www.amazon.com/FPGA-Prototyping-VHDL-Examples-Spartan-3/dp/0470185317/

 

Digital Design and Computer Architecture (first or second edition, I have both, the second edition does not add much of value IMO.)

https://www.amazon.com/Digital-Design-Computer-Architecture-Second/dp/0123944244/

 

The secret to using FPGAs is a mindset. You are NOT PROGRAMMING! If you approach FPGAs from a software perspective you will not get very far. There is a reason VHDL and Verilog are call Hardware Description Languages (HDLs), and is actually what the "HDL" mean in VHDL (the "V" is another long acronym).

 

When you "code" for an FPGA you are "describing hardware". You really have to understand that and think that way. Think about how you would build the circuit using 74-logic and you will find it translates very well to HDL. You have to think in terms of gates, multiplexers, memories, flip-flops, registers, etc.

 

Also realize that both VHDL and Verilog have a lot of syntax that is not "synthesizable". You can use both languages for doing circuit "simulation" where you never intend the circuit to run on a real FPGA. But I assume everyone here wants their designs to run on a real FPGA and interface with real hardware, so you need to write your HDL to be synthesizable, which means you will be restricted to a subset of the languages. You have to be careful when starting out, don't get mislead. Do not look for "variables" and there are not loop-constructs (technically there are, but they do not do what you think they do) in synthesizable HDL. You use signals, registers, and Finite State Machines (FSMs) to sequence things that need to happen in series (because hardware always works in parallel.)

 

As for sizing FPGAs, it is very hard to get a sense of how big they are even among the same manufacturer. For example, the Spartan 3E FPGA I used for the F18A is specified in "gates", i.e. 50K, 100K, 250K, 500K, 1000K, etc. But the Spartan 6 line (and other Xilinx FPGAs for that matter) are measured in "logic cells" which consists of a few factors like CLB (configurable logic blocks), LUTs (lookup tables), etc. Some actual examples that may or may not help:

 

1. The F18A uses a Spartan 3E 250K, which is a little smaller and a Spartan 6 LX9. The whole F18A design *without* the GPU was under 50% utilization of the FPGAs resources. After adding all the other features like the GPU, stack instructions, DMA, etc. the utilization is about 96% of the FPGA.

 

2. I did the Joust coin-op computer as a complete SoC on a Spartan 3E 500K and Spartan 6 LX16. I needed external memory in both cases due to the 48K of RAM in the system, plug the 40K or so of ROM. The design includes a 6809 CPU, 6800 CPU, the custom Blitter, two 6821 PIAs, video circuits, dedicated PROMs, glue logic, etc. All of that was very comfortable in the 3E-500K and the LX16.

 

3. A complete 99/4A SoC with F18A could fit in the 3E-500K or LX16.

 

When you start looking at the Spartan 6 LX16, LX25, and LX45, those have a lot of logic in them for just about anything you would want to do. Even 32-bit or 64-bit CPUs will fit happily in the LX25 or LX45.

  • Like 3
Link to comment
Share on other sites

I can recommend you WaveShare's Open3S500E board. This is what I use. It has a Spartan 3E 500K on it, is less expensive and has nice expansion capability. For me it is the most flexible system. Unfortunately the older Xilinx Spartan-3 is used for this board.

 

Here is an older post I made on the other FPGA-Thread started by speccery, where I already leave some notes to this dev board: http://atariage.com/forums/topic/255855-ti-994a-with-a-pipistrello-fpga-board/page-7?do=findComment&comment=3617089

 

 

 

Send from my Hackinosh using Firefox

Edited by HackMac
  • Like 1
Link to comment
Share on other sites

Thanks Matt. This is great info. It is starting to sink in. The book I have has (among other examples) a VGA video output module. The logic makes perfect sense to me and looks surprisingly simple. But there are hidden dangers. For example there is a difference in Verilog between = and <= but my book only really glosses over it. I'm looking forward to getting stuck in!

  • Like 1
Link to comment
Share on other sites

Hello.

Thanks for your efforts! Your VDP replacement is useful for many platforms.

 

Are you going to publicly release the 9900 and the VDP cores?. Do you yhink it may be useful for other ptojects?

 

Kind regards,

 


1. Digilent Spartan 3E Starter (this is the board the F18A was initially developed on: http://store.digilentinc.com/spartan-3e-starter-board-limited-time/

Digilent makes good stuff and they have all kinds of boards in many ranges, lots of I/O boards, etc.

 

2. Of course the Gadget Factory: http://store.gadgetfactory.net/

The Papilio boards are nice and there are a lot of add-on boards for I/O and such.

 

3. Xess.com: http://www.xess.com/

1. The F18A uses a Spartan 3E 250K, which is a little smaller and a Spartan 6 LX9. The whole F18A design *without* the GPU was under 50% utilization of the FPGAs resources. After adding all the other features like the GPU, stack instructions, DMA, etc. the utilization is about 96% of the FPGA.

 

3. A complete 99/4A SoC with F18A could fit in the 3E-500K or LX16.

 

 

 

Have you considered to port it to the MiST board? It has tons of cores ported already :)

https://github.com/mist-devel/mist-board/wiki/GettingStarted

 

 

If your Mojo board has the Spartan 6 on it you can definitely do CPUs on it. :) Multiprocessors even. My project could fit at least another TMS9900 core on the same FPGA, but need to get the first one working properly yet ;)

 

Edited by timofonic
Link to comment
Share on other sites

  • 1 month later...

Wow it's been a long while I posted anything!

Just to let people potentially interested in my project(s) know, I have not abandoned the project, I've just been very preoccupied with other things in life. I thought I'll drop an update in here, since it's been - shall we say - unique.

 

As a quick summary, this year for me has been kind of weird: I started in my current job in the beginning of the year - that was a major change for me. In this new company I pulled together our financing round - and that was a lot of work which extended to my summer holidays, actually the closing of the round occurred during my summer vacation so the early part of my vacation did not resemble vacation that much, working remotely would be a better indication. But the job did get done. Quite stressful, despite having done funding rounds in the past they still take a great deal of energy. The wonderful world of high tech...

 

Concurrently with that I went through divorce and all the logistics that goes with that. Not much fun as I am pretty sure (unfortunately) many people here too would know. Thus big changes in private life too.

 

But I did meet a wonderful woman in the beginning of the summer - and instead of what I thought could have become a retrocomputing intensive summer vacation, I've been having a more usual summer vacation despite the intrusion of work.

 

So there it is - real life has kept me busy, but I am definitely going to complete the TMS9900 FPGA CPU project, and I'm looking forward to diving back in to that project. I'm actually finding myself pretty full of energy and curiosity to get this thing working :)

  • Like 6
Link to comment
Share on other sites

  • 2 weeks later...

A quick update... after probably 3 months of silence I found some time on a long haul flight to work on the CPU core. Prior to this I several times tried to restart debugging, but I found it took a while to remember where I was...

 

I started by improving the functionality of the overflow flag and added the missing parity bit. Now I think I have all the flags done, but I am sure there still bugs there. I also added some new debugging capability: now when the CPU is in single stepping mode there are two new debug registers which record the address and data of the last write operation. I log that information into a file during single stepping and I created a simple python script to compare that to a similar log from my slightly modified classic99 version. And that's where I am now - so back into some sort of speed with new debugging tools. Now all I need is more time to figure out what is not working properly, as I still can't boot successfully with the TI Basic ROMs. Using this new debugging workflow should make that faster and easier :)

  • Like 5
Link to comment
Share on other sites

  • 4 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...