Quickdev2 Progress

After building the quickdev16 in the summer of 2010 we decided to work on a 2nd version off the quickdev16, which we called quickdev2. All this work was done in the summer of 2010 but i never got around to finish the project nor to blog about it. So here is a little overview:

The next quickdev should be a little bit faster and should have more features. So we selected a new CPU, the Atmel at90usb1287 that can handle USB via hardware and has more SRAM. To simplify the logic part we opted for a XILINX CPLD xc95144xl. We used a bigger Cypress 16-Mbit SRAM CY62167E. The AVR would expose the USB interface to the PC side, as a masstorage device using the LUFA library. The AVR has a data bus to the CPLD. The CPLD is also connected to the external SRAM. In the CPLD we implemented a SREG, counter, commandmuxer and memory interface in Verilog.

The system top looks like this:

module system (

    inout [7:0] sram_data,
    output [20:0] sram_addr,
    output sram_oe_n,
    output sram_we_n,
    output sram_ce_n,


    output [7:0] snes_data,
    input [20:0] snes_addr,

    inout [7:0] avr_data,
    input [7:0] avr_ctrl,
    input avr_clk,
    output [7:0] debug
);

We have a 8 bit data bus and 21 bit address bus to the SRAM. 3 extra lines for OE,WE and CE. Then there is the same setup for the SNES side. 8 Data and 21 address line. No more control lines to the SNES are currently implemented. There is a 8 bit data and 8 bit control bus to the AVR. Finally we have a CLK line from the AVR to the CPLD and a 8bit debug bus. The AVR clocks its own clock into the CPLD, which is feed into a DCM and is divided by 2. This clock signal is feed into the FSM and SREG internally. The avr_ctrl bus is feed into a commandmuxer which drives the other components on the CPLD. Foremost it drives a FSM which manages the data routing between AVR <-> SRAM and SRAM <-> SNES.

module bus_fsm #(
    parameter DWIDTH = 8
)(
    input                   clk,
    input                   reset,
    input                   we_n,
    input                   oe_n,
    inout   [DWIDTH-1:0]    avr,
    inout   [DWIDTH-1:0]    sram,
    inout   [7:0]           debug
);

parameter SIZE   =  3;
parameter IDLE    = 3'b000;
parameter WE      = 3'b001;
parameter BUFAVR  = 3'b010;
parameter BUFSRAM = 3'b011;
parameter OE      = 3'b100;


reg   [SIZE-1:0]          state;
reg   [SIZE-1:0]          next_state;
reg   [DWIDTH-1:0]        buffer_avr;
reg   [DWIDTH-1:0]        buffer_sram;
reg   [DWIDTH-1:0]        buffer;

assign avr = buffer_avr;
assign sram = buffer_sram;

always @ (state or we_n or oe_n)
begin : FSM_COMBO
    next_state = 3'b000;
    case(state)
    IDLE : if (we_n == 1'b0) begin
            next_state = BUFAVR;
        end else if (oe_n == 1'b0) begin
            next_state= BUFSRAM;
        end else begin
            next_state = IDLE;
        end
    BUFAVR: if (we_n == 1'b0) begin
            next_state = WE;
        end else begin
            next_state = IDLE;
        end
    BUFSRAM: if (oe_n == 1'b0) begin
            next_state = OE;
        end else begin
            next_state = IDLE;
        end
    OE : if (oe_n == 1'b0) begin
            next_state = BUFSRAM;
        end else begin
            next_state = IDLE;
        end
    WE : if (we_n == 1'b0) begin
            next_state = BUFAVR;
        end else begin
            next_state = IDLE;
        end
  endcase
end

//----------Seq Logic-----------------------------
always @ (posedge clk)
begin : FSM_SEQ
    if (reset == 1'b1) begin
        state < = #1 IDLE;
    end else begin
        state <= #1 next_state;
  end
end

//----------Output Logic-----------------------------
always @ (state)
begin : OUTPUT_LOGIC
  case(state)
    IDLE: begin
        buffer_avr <= 8'bz;
        buffer_sram <= 8'bz;
        buffer <= 8'bz;
    end
    WE: begin
        buffer_sram <= buffer;
    end
    OE: begin
        buffer_avr <= buffer;
    end
    BUFSRAM : begin
        buffer <= sram;
    end
    BUFAVR : begin
        buffer <= avr;
    end
    default : begin
        buffer_avr <= 8'bz;
        buffer_sram <= 8'bz;
    end
  endcase
end

assign debug = { clk,we_n,oe_n,state,2'bz};
endmodule

From the AVR software side a SRAM write looks like this.


void sreg_set(uint32_t addr)
{


    uint8_t i = 21;
    #if SREG_DEBUG 
    uart_putstring("sreg_set\n\r");
    #endif
    SET_AVR_SREG_EN_HI();
    while(i--) {
        if ((addr & ( 1L < < i))){
            SET_AVR_SI_HI();
    #if SREG_DEBUG 
            uart_putchar('1');
    #endif
        } else {
            SET_AVR_SI_LO();
    #if SREG_DEBUG 
            uart_putchar('0');
    #endif
        }
        SET_AVR_SREG_EN_LO();
        SET_AVR_SREG_EN_HI();
    }
    #if SREG_DEBUG 
    uart_putstring("\n\r");
    #endif
}

void SRAM_write(uint32_t addr, uint8_t data)
{

    // set direction of data port
    AVR_DATA_DIR = 0xff;
    // load address
    sreg_set(addr);
    // disable OE and WE
    SET_AVR_OE_HI();
    SET_AVR_WE_HI();
    // wait for FSM to go into IDLE state
    nop();
    nop();
    // write data
    AVR_DATA = data;
    // enable WE
    SET_AVR_WE_LO();
    // wait for FSM to go into WE state
    nop();
    nop();
    nop();
    nop();
    // disable WE
    SET_AVR_WE_HI();
}

The development was done on our new prototype board, which Max layouted for us. I used an AVR Dragon for the AVR programming part and debugging via JTAG. For the CPLD side i used a homebrew Xilinx Platform cable alongside with ISE. I quickly stopped using the IDE and just cooked my own Makefile using the Xilinx commandline tools.

Most of the logic was developed using a testbench and running through iverilog. But having a module working in a testbench doesn't mean that it works on real hardware. We had todo a lot of debugging on the real hardware. This involved a lot of test probe soldering. Luckily we had my 8bit Saleae LA which helped a lot to track done some Problems. But the biggest issue was to get the timing right with the FSM for the memory bus.

We hacked this in a 3 day weekend sprint and implemented the SRAM read and write from the AVR side. But then we hit a wall and didn't implement the SNES side. The project lost some traction. Max had moved to Berlin we couldn't work together on the project anymore. We lost a little interest because the sd2snes project achieved what we we intended to do and Ikari_01 did far better job then we did. I recently got word the sd2snes is considered stable and a first batch is sold.

We plan to start working on this again. To implement the SNES side of the memory we would need to increase the speed of the FSM to get it into IDLE state and then in SNES state within 120ns or 200ns after the SNES does a CS on the cartridge. Since the AVR drives the CPLD clock with 20MHz, we would need some kind of PPL to run the FSM with like 60MHz, which should be plenty to run the FSM for the SNES SRAM read.

We appreciate any comment or suggestion for the hardware design of this project.

Super Nintendo Talk

A while ago i held a talk at the ccc in cologne about my favorite game console the Super Nintendo. This talk covers the Super Nintendo technology in detail. Starting with the CPU and PPU, covering the cartridge memory maps and showing most of the custom chips which where used on cartridges. I also show development hardware, copier stations and the current available flashcarts. The topic emulation is also covered . The second part of the talk is about the quickdev16 project, which i did with my friend max in 2009. We built a flashcart for the SNES which is useful for developing homebrew software. The talk sums up all the details i learned during the research i made to built this kind of cartridge. I uploaded the slides, maybe someone find this useful to dive into the SNES world.

First Quickdev16 PCB is working

Not “out of the box” but with only slightly changes on the software part, the new quickdev16 PCBs are working. Their shape fit the SNES cartslot, the changes in hardware design and parts worked out great and we have a kind of stable firmware and upload tool.

When you turn on the SNES, the microcontroller extracts a small loader-rom into the cartridge RAM that is mapped into the SNES addressspace. This one copies itself to SNES’s WRAM and jumps into it. So the cartridge RAM is unaccessed and we can safely switch back to the AVR mode to push a real payload rom onto the cartridge. We are also working on a shared memory function so that we can use the cartridge RAM to exchange infomation between the AVR and the SNES. This will be used to display a proper Progressbar while uploading a rom.

As usal you can use our patched version of ucon64 – even under windows – to upload a game to the quickdev16. When the upload is done, the SNES reset line is pulled by quickdev16 and the game starts. When you press the reset button, you only reset the game, not the quickdev16 – it acts like a normal cart. When you press the reset button during the upload process or while watching the loaderscreen, you reset the quickdev and can abort uploads or just restart the quickdev16 – thats a really usefull feature. To initiate the upload of a new game, just start the upload process with ucon, the quickdev switches to the loader mode by itself and receives the new ROM.

So the steps are now to improve the loader code, finish the progress bar stuff, figure out how to solder the PCBs faster than now and add some minor features. Stay tuned for updates, it’s not too long to the release.

svgallery=

We call it ‘QuickDev16 USB’

Finally we found a better name for the snesram and renamed it to ‘QuickDev16 USB’. Final PCB layouts are ready and will be send to china soon. So in about 2 weeks we will have our first PCBs.

Confirmed Features:

  • 16 MBit Sram for Rom storage
  • ATmega644 MCU for housekeeping
  • USB connection for ROM upload
  • ucon64 software compatibel
  • PAL/NTSC CICs are supported
  • Lo/Hirom support
  • Reset trigger from cartridge possible
  • AVR USB Bootloader for quick firmware uploads
  • Snes bootloader intro
  • Snes powered, no power source needed

Stay tuned for more features, especially debugging helpers

pov_front_2.6

pov_back_2.6

Features Features Features…

Things are going well. Have added some features to the software side and also got some stuff working hardware wise.

Can confirm that US/JAP roms are working.Only tested EU roms before. Used my japanese Nintendo junior and a japanese CIC to confirm that the snesram is working with that setup too.

Max and i added an bootloader to the AVR software toolchain. Now its possible to flash the AVR firmware via the same USB cable as for the normal bulk transfer. So no extra ISP programmer is needed to change the AVR firmware. This is super fast, can flash the 16kb client side firmware in like 3 secs.

Added a reset line trigger to the snes bus. Now the client software can reset the snes after uploading the software. So its possbile to push a rom via ucon64 from the pc and then reset is done by ucon64 and the firmware. No interaction needed from there.

Max is refactoring the schematics so that we can send them over to the pcb fab soon. Stay tuned.

New Hardware Revision

Max took a quick break from his vacations and was able to work on the new hardware revision of the snesram. Its mainly a bugfix to version 0.1 . We also did some cost reductions. Most obvious is to go for 2 Mbyte of sram instead of 4Mbyte. It just make the PCB smaller and less complex. I guess this should be alright with most peoples needs. We gonna print a small amount of PCB and will take pre-orders as soon as we know they will arrive. Not sure about the final price, depends on the PCB costs and if we get better prices for the sram. Stay tuned.

Changes in Detail:

* Add AVR reset button
* Fix CS bug and add additional gate
* Reduce to 2 Mbytes for 16 Mbits games
* Snes reset line trigger
* No FTDI for the serial line
* Add RX/TX to pin header
* Model Snes connector header
* 1,2 mm PCB for direct plug
* Blacksolder Mask
* White silk screen

Preview:

Front

Front

Back

Back

Ucon64 Support

The software is coming down smoothly. Ported the usb uploader code to ucon64. Also Hirom support ist working now with ucon64 autodedection. So the Snesram board is becoming quite handy for daily dev work.

This hardware revision has 2 bugs which doesn’t make it possible to print pcbs now. There is additional OR gate needed to drive the CS line properly and an AVR reset switch is missing too. I guess when Max is back from his holiday he wants to fix this in the pcb layout. I think it would be smart to only use 4 sram chips and to have 2mb and not 4mb. Just to reduce the cost and get some more space on the pcb. If there is an interest from the community to support this hardware revision we gonna print some pcbs and sell them. Otherwise we gonna start working on a enhanced version soon.

A video showing the hardware with ucon64 in action…

[flash]http://www.youtube.com/watch?v=1mfq6yJA1MQ[/flash]