6502.org
http://forum.6502.org/

6502 Playground - with Arlet's core and 128K SRAM.
http://forum.6502.org/viewtopic.php?f=10&t=2557
Page 1 of 4

Author:  enso [ Fri Jun 28, 2013 10:14 pm ]
Post subject:  6502 Playground - with Arlet's core and 128K SRAM.

I've been making progress with my 6502 Playground board conceived in topic http://forum.6502.org/viewtopic.php?f=4&t=2322. It's a board with XC3S700AN, a 128K SRAM, a 65C02 or '16, a 60MHz crystal oscillator and voltage regulaters, plus lots of IO.
Attachment:
6502play.c.jpg
6502play.c.jpg [ 53.9 KiB | Viewed 2152 times ]

While similar projects have been documented here, I wanted to configure the board with Arlet's core to get the kinks out.

Getting the core to work with a BRAM is pretty easy. The SRAM is a little more work. There has been some discussion about using async SRAMS. The problem is that back-to-back writes required for pushing data onto the stack leave the Write Enable line on for 2 cycles, which may or may not accomplish the desired goal.

To avoid problems, I am decoding addresses so that page 1 is using a BRAM. While debugging, I use the BRAM for page 0 and 2. Page $FF contains vectors, so into the BRAM it goes.

Arlet was kind enough to point out the obvious fact (that I wasn't paying attention to) - BRAMS are synchronous, but SRAMs are not, so SRAM output must be pipelined, and care must be taken with muxing the results (since they mux depends on previous cycle's selects).

I created a simple core for the SRAM, and after some hammering got it to work - sort of. I wrote a simple LED blinker:
Code:
CTR0 equ $200
CTR1 equ CTR0+1
CTR2 equ CTR0+2
  org $237
start:
;
; blink using a 3-byte counter in memory
;
bl:
  lda   #0
  sta   CTR0
  sta   CTR1
  lda   #40
  sta   CTR2
bl1:
  dec   CTR0
  bne   bl1
  dec   CTR1
  bne   bl1
  dec   CTR2
  bne   bl1
  lda   $C000
  jmp   bl

  org $7FC
  dw start


At 30MHz this blinks the LED nicely ($C000 is decoded to toggle the LED). But, it blinks twice as fast with the variables in SRAM (CTR0 set to $2000 or anything else outside BRAM pages).

I am somewhat perplexed.

At 60MHz the system will not blink when the variables are in the SRAM. It should really go to 100MHz, so I must have done something wrong...

Author:  enso [ Sat Jun 29, 2013 3:45 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Connected a UART. Communicating via a 3.3V FTDI USB-serial port to my linux box.

I am using the UART from Xilinx, the one that comes with Picoblaze. I wrapped it into a module for easy interfacing (I will keep updating here):
Code:
/******************************************************************************
 UART  - wrapper around the Xilinx Picoblaze uart.
 
 Files required:
   bbfifo_16x8.v
   kcuart_rx.v
   kcuart_tx.v
   uart_rx.v
   uart-tx.v

To connect to arlet's 6502 core, I decode an 8-byte memory location (with SEL).
Base address is the status register when read.  Base+1 is the data register,
which can be read or written.  In the future I may add other registers.
     
******************************************************************************/
module mUART(
  input CLK
, input [2:0] addr
, input SEL
, input WE
, input [7:0] DI
, output reg [7:0] DO
// interface to hardware
, output TX
, input RX
);
//-----------------------------------------------------------------------------
// The UART requires pulses at the rate of BAUD * 16.  At 30MHz, use a 16-bit
// shift register with a single bit on...This provides 115200 * 16 (close to)
wire baud_x16;
SRL16 #(.INIT(1)) baudshifter1 (baud_x16,1,1,1,1,CLK,baud_x16);
//
wire tx_full;
wire tx_half_full;
wire rx_full;
wire rx_half_full;
wire rx_data_present;
wire [7:0] rx_data;
wire do_tx;
wire do_rx;
//-----------------------------------------------------------------------------
// uart tx
//-----------------------------------------------------------------------------
uart_tx utx(
    DI,                     //data to send out
    do_tx,
    0,                      //reset buffer
    baud_x16,               // baud rate x 16 pulses
    TX,                     // output pin
    tx_full,
    tx_half_full,
    CLK);
//-----------------------------------------------------------------------------
// uart rx
//-----------------------------------------------------------------------------
uart_rx urx(
    RX,                 //input pin
    rx_data[7:0],       //input data
    do_rx,              //when strobed, consider read done
    0,                  //rx reset buffer
    baud_x16,           //baud
    rx_data_present,
    rx_full,
    rx_half_full,
    CLK); 
//-----------------------------------------------------------------------------
// mux for the output value: even=status odd=data
always @ (posedge CLK)
  if(SEL & ~WE)
    if(addr[0])
        DO <= rx_data[7:0];
    else
      DO <= {rx_data_present, rx_full, rx_half_full,2'b00, tx_full, tx_half_full};
  else
    DO <= 8'h00;
 
assign do_tx = WE & SEL;
assign do_rx = ~WE & SEL & addr[0];  //any odd address acks read

endmodule


And here is (not the most elegant) 6502 code to send and receive characters, blocking:
Code:
UART_BASE equ $C008           ;C008-C00F dedicated to the UART
UART_STATUS equ UART_BASE
UART_DATA   equ UART_BASE+1

emit:
  tax                 ;move character to x for now
  lda  UART_STATUS
  and  #$02           ;buffer full?
  bne  emit           ;yes, keep trying
  stx  UART_DATA     
  txa
  rts

key:
  lda   UART_STATUS
  and   #$40          ;rx data present?
  beq   key           ;no, keep trying
  lda   UART_DATA
  rts


Attachment:
6502play.c.term.jpg
6502play.c.term.jpg [ 46.71 KiB | Viewed 2134 times ]

With good looking fonts, too! :lol:

I still have to find out the SRAM/BRAM blink rate problem, but now I can write a debugger...

Author:  MichaelM [ Sat Jun 29, 2013 4:05 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Pretty cool. Keep posting on your progress.

Author:  Arlet [ Sat Jun 29, 2013 4:25 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

I recommend making a testbench with an SRAM model, and running a simulation.

Author:  Arlet [ Sat Jun 29, 2013 4:33 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Quote:
At 60MHz the system will not blink when the variables are in the SRAM. It should really go to 100MHz, so I must have done something wrong...

You base this 100 MHz on the fact that you're using 10 ns SRAM ? You're forgetting that the FPGA also has delays to get the internal data on its external pins, and the other way around. Somewhere buried in the FPGA datasheet you should be able to find them, but expect them to be several ns. In addition you have delays on the board.

Author:  enso [ Sat Jun 29, 2013 4:43 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

I am afraid I will wind up doing just that - simulate.

The core is connected to the BRAM with just a few lines of verilog, so I am pretty sure it's not there. That leaves the SRAM - it must somehow skip something - although I can't imagine what can happen to make the loop run twice as fast. It's very consistent at different clock rates, and running it slowly does not reveal anything obvious (the decrements are working as expected).

How does one go about creating a testbench?

This is a -5 part, so it should be pretty quick, and it seems almost 20ns should be enough time to get data in and out.. The board propagation delays should not be too bad, with less than 25mm maximum trace length.

Author:  enso [ Sat Jun 29, 2013 4:46 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

On the positive side, the entire system is very small:
Code:
Logic Distribution:
  Number of occupied Slices:            371 out of   5,888    6%

That's with the UART, a SRAM controller and some minor IO decoding.

Author:  Arlet [ Sat Jun 29, 2013 5:00 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Can you post your SRAM code ?
Quote:
This is a -5 part, so it should be pretty quick, and it seems almost 20ns should be enough time to get data in and out
Running at 60 MHz, you only have 16 ns, of which 10 ns are needed by the SRAM. That only leaves 6 ns for the FPGA input, output, and external delays.

You could run a simple test where you wire two pins from the FPGA together. You write to one pin, and read on another. Now, toggle the output pin with each clock, and compare with input. Increase the clock. For some clock speed, you'll see that the input will no longer have the same value as the output. From that speed, you can deduce the delays.

Author:  enso [ Sat Jun 29, 2013 5:13 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

The SRAM controller:
Code:
/******************************************************************************
 a controller for a 128K async SRAM.
 Makes it work like a BRAM
******************************************************************************/
module mSRAM128K(
  input sclk
, input en              //1 means do enable;
, input we
, input  [16: 0] ab
, input  [ 7: 0] di
, output reg [ 7: 0] do
// interface to the real chip
, output [16: 0] xab
, inout  [ 7: 0] xdb
, output  xcs_
, output  xoe_
, output  xwe_
);
  assign xcs_ = ~en;    //chip select is inverted
  assign xwe_ = ~we;    //we is inverted
  assign xoe_ = 1'b0;     //see SRAM timing diagrams
  assign xab  = ab;     //address bus permanently connected
  //
  // Implement a tri-state circuit for the inout xdb
  // Reading a deselected chip should return 0 if pulldowns are enabled.
  wire [7:0] xin = we ? 8'bZ : xdb ; //on read, let data in   
  assign xdb     = we ? di   : 8'bZ; //on write, let data out 
  //
  // Return read result next cycle
  always @ (posedge sclk)
    if(en & ~we)  //on write, output 0 - for some reason it's FF
      do <= xin;
    else
      do <= 8'h00;
         

endmodule

Author:  enso [ Sat Jun 29, 2013 5:16 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

All modules (SRAM, BRAM and IO) output 0 when deselected, so I can mux by ORing.
Code:
// Memory address selects
assign IO_SEL = (CPU_AB[15:8]==8'hC0); // C0xx
assign BRAM_SEL = (CPU_AB[15:8]==8'hFF)|(CPU_AB[15:9]==7'h00)|(CPU_AB[15:8]==8'h02);//page 0,1,2 or FF use BRAM...
assign IO_C000_SEL = IO_SEL & (CPU_AB[7:0]==8'h0);
assign UART_SEL =    IO_SEL & (CPU_AB[7:3]==5'h1);
assign SRAM_SEL = ~(IO_SEL | BRAM_SEL);


//DI mux.  Since we are careful about setting unselected values to 0, we can just or all of them in
assign CPU_DI[7:0] = BRAM_DO | SRAM_DO | UART_DO;


I guess I could tighten up the SRAM select code...

Author:  Arlet [ Sat Jun 29, 2013 6:27 am ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Hmm.. I don't see anything suspicious in the code.

Author:  enso [ Sat Jun 29, 2013 3:52 pm ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

It's a pretty good puzzle. The setup - Arlet's core and BRAM and SRAM. Stack in page 1, code also in a BRAM.
Code:
           Variables in:
          BRAM       SRAM
60MHz      OK        FAIL
30MHz      OK        2x blink
15MHz      OK        2x blink
1MHz       OK        2x blink


At 1Hz, observing the address bus and the DIN bus with a 4-digit LED display, things look convincingly similar with SRAM and BRAM... Wait, I didn't think much of it, but the inner loop took 9 cycles which is too long. [EDIT] No, 9 cycles is right:
Code:
bl1:
  dec   CTR0    ;6;
  bne   bl1     ;3;  branch taken


I should really count up the cycles to see which blink rate makes sense at a given frequency...

Author:  enso [ Sat Jun 29, 2013 4:33 pm ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

Ok, the blink rate is really about twice what it should be when counters are in the SRAM. So, one working theory is that D7 is reading or writing low, causing the counters to run out faster. Although that would make it more than 2x, and it seems I am a little under 2x.

I guess the thing to do (other than simulation) is to write a simple memory test.

Author:  enso [ Sat Jun 29, 2013 7:41 pm ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

I wrote a simple memory test - filling a page with sequential bytes. Sure enough, BRAMS look good but looks like the SRAMS are missing the top 2(!) bits. I have a 6-bit memory connected. I am checking the schematics and the connections now.

Author:  enso [ Sat Jun 29, 2013 8:03 pm ]
Post subject:  Re: 6502 Playground - with Arlet's core and 128K SRAM.

It is not a wiring problem either. My first assumption was that it's another BGA problem. But no!

I configured the FPGA to set these 2 pins high, then low. I can read the voltages off the J leads of the SRAM, and they do go high and low. So the physical connection between the FPGA and the pads is ok, at least as far as DC goes.

Somehow the verilog code is incorrect, but just for the 2 high bits...

EDIT:
Modified the SRAM core to set the high 2 bits on write, that works. That implies that I am only getting 6 bits out of Arlet's core. When I OR the high 2 bits of DO (as it enters the SRAM in the SRAM instance) from the cpu high, memory is written with 2 high bits set... Otherwise, the 2 high bits are always low, for the SRAM only.

So, the SRAM core is not the problem - feeding high bits into it works.

Switching bits 6/7 with 0/1 with in the ucf file... Will it write the top 6 bits and leave low 2 bits 0? It just got worse:

0500: 00 00 00 03 04 04 04 07 08 08 08 0B 0C 0C 0C 0F

It wrote 3, but not 1 or 2! Magic. It only writes bits 1 and 2 when both are set! It implies that earlier, had I looked at 05C0 the high bits were on - but I didn't bother looking up there.

Arlet - any thought? I will continue looking.

Page 1 of 4 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/