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

65ORG16.b Core
http://forum.6502.org/viewtopic.php?f=10&t=1842
Page 8 of 24

Author:  BigEd [ Sun Feb 26, 2012 7:27 pm ]
Post subject: 

fachat wrote:
Do you know how old this design is? There is no date on the page

André


Maybe 1993? (Although the pages from the webserver are dated April and May 2000, and archive.org has a version from 1997.)

Cheers
Ed

Author:  Tor [ Mon Feb 27, 2012 8:34 am ]
Post subject: 

fachat wrote:
BigEd wrote:


Do you know how old this design is? There is no date on the page

André

The Last-Modified date is 10 May 2000 02:48:27 GMT for the first page and 30 Apr 2000 17:41:48 GMT for the second page (the instructions page).

Edit: Ah, BigEd beat me to it. I didn't see the next page of the topic.

-Tor

Author:  ElEctric_EyE [ Mon Feb 27, 2012 3:45 pm ]
Post subject: 

Been thinking about the Acc-Acc transfers...

I think it's time to define some new base opcodes for the A accumulator. By base I mean in the original 6502 $00-$FF region.

I chose the columns $03 & $0B. Specifically, $BB, $AB & $9B for TAB, TAC, & TAD and $B3, $A3 & $93 for TBA, TCA, TDA. Other Acc to Acc transfers will depend on bits 11, 10, 9 & 8. Still working on it...

Author:  ElEctric_EyE [ Mon Feb 27, 2012 5:18 pm ]
Post subject: 

Ok, now I am getting confused. Could be because I am going back and forth between working on cars and the code, heh. But this is what I have so far for Acc to Acc transfers using the dst_reg. What about the src_reg? I have run out and am confused as to which Acc should be the src and which Acc is the dest.
Code:
16'b0000_00xx_1011_1011:   // TBA
            dst_reg <= SEL_B;
            
      16'b0000_00xx_1010_1011:   // TCA
            dst_reg <= SEL_D;
            
      16'b0000_00xx_1001_1011:   // TDA
            dst_reg <= SEL_E;
            
      16'b0000_01xx_1011_1011:   // TAB
            dst_reg <= SEL_A;
               
      16'b0000_01xx_1010_1011:   // TCB
            dst_reg <= SEL_D;
            
      16'b0000_01xx_1001_1011:   // TDB
            dst_reg <= SEL_E;
            
      16'b0000_10xx_1011_1011:   // TAC
            dst_reg <= SEL_A;
            
      16'b0000_10xx_1010_1011:   // TBC
            dst_reg <= SEL_B;
            
      16'b0000_10xx_1001_1011:   // TDC
            dst_reg <= SEL_E;
            
      16'b0000_11xx_1011_1011:   // TAD
            dst_reg <= SEL_A;
         
      16'b0000_11xx_1010_1011:   // TBD
            dst_reg <= SEL_B;
            
      16'b0000_11xx_1001_1011:   // TCD
            dst_reg <= SEL_D;
            
            
      default: case( IR[9:8] )
                  2'b00: dst_reg <= SEL_A;
                  2'b01: dst_reg <= SEL_B;
                  2'b10: dst_reg <= SEL_D;
                  2'b11: dst_reg <= SEL_E;
                     default: dst_reg <= SEL_A;
               endcase


SEL_D and SEL_E are actually the C and D Accumulators respectively.

Author:  Arlet [ Mon Feb 27, 2012 6:06 pm ]
Post subject: 

In the TAX instruction, the 'A' is the source, and 'X' is the destination. So src_reg should be SEL_A, and dst_reg should be SEL_X.

Author:  ElEctric_EyE [ Mon Feb 27, 2012 7:33 pm ]
Post subject: 

I will rename the C flag (carry) so I can use SEL_C to make the code less confusing. Right now there's a conflict if I try to use SEL_C. For arguments sake SEL_C is Accumulator C.

But, consider a TBC and a TCB. Since the src_reg and dest_reg both are MUX'd into SEL_B-SEL_C. We could pick whether to put these opcode definitions in a dest_reg CASEX or a src_reg CASEX?

I will try a simulation of what I have so far...

Author:  Arlet [ Mon Feb 27, 2012 7:48 pm ]
Post subject: 

ElEctric_EyE wrote:
But, consider a TBC and a TCB. Since the src_reg and dest_reg both are MUX'd into SEL_B-SEL_C. We could pick whether to put these opcode definitions in a dest_reg CASEX or a src_reg CASEX?


I'm not really following you here.

For a TBC instruction, the src_reg should be SEL_B, and the dst_reg should be SEL_C. The TBC instruction is then executed in two cycles. In the first cycle, the src_reg is read from the register file, so it reads register 'B'. In the second cycle, the result is written to the dst_reg, so it writes register 'C'.

So, dst_reg always points to the register where the ultimate result of the operation is stored, and src_reg points to a register that is read during the instruction to get an operand.

Author:  ElEctric_EyE [ Mon Feb 27, 2012 9:55 pm ]
Post subject: 

I'll try to explain the way I have understood the progression.

first was this code, I'll use TAX etc. as an example.
Code:
...
16'b0000_0000_101x_xx10:   // LDX, TAX, TBX, TSX
            dst_reg <= SEL_X;
...
default:  dst_reg <= SEL_A...


then I modified the default with your help to get TBX, TCX, TDX etc.
Code:
16'b0000_00xx_101x_xx10:   // LDX, TAX, TBX, TSX
            dst_reg <= SEL_X;
...
default: case( IR[9:8] )
                  2'b00: dst_reg <= SEL_A;
                  2'b01: dst_reg <= SEL_B;
                  2'b10: dst_reg <= SEL_C;
                  2'b11: dst_reg <= SEL_D;


So, it makes sense to do this doesn't it?:
Code:
...
16'b0000_00xx_101x_xx10:   // LDX, TAX, TBX, TSX
            dst_reg <= SEL_X;
...
16'b0000_00xx_1011_1011:   // TBA
            dst_reg <= SEL_B;
      16'b0000_00xx_1010_1011:   // TCA
            dst_reg <= SEL_C;
      16'b0000_00xx_1001_1011:   // TDA
            dst_reg <= SEL_D;
            
      16'b0000_01xx_1011_1011:   // TAB
            dst_reg <= SEL_A;
      16'b0000_01xx_1010_1011:   // TCB
            dst_reg <= SEL_C;
      16'b0000_01xx_1001_1011:   // TDB
            dst_reg <= SEL_D;
            
      16'b0000_10xx_1011_1011:   // TAC
            dst_reg <= SEL_A;
      16'b0000_10xx_1010_1011:   // TBC
            dst_reg <= SEL_B;
      16'b0000_10xx_1001_1011:   // TDC
            dst_reg <= SEL_D;
            
      16'b0000_11xx_1011_1011:   // TAD
            dst_reg <= SEL_A;
      16'b0000_11xx_1010_1011:   // TBD
            dst_reg <= SEL_B;
      16'b0000_11xx_1001_1011:   // TCD
            dst_reg <= SEL_D;
            
            
      default: case( IR[9:8] )
                  2'b00: dst_reg <= SEL_A;
                  2'b01: dst_reg <= SEL_B;
                  2'b10: dst_reg <= SEL_C;
                  2'b11: dst_reg <= SEL_D;
                         default: dst_reg <= SEL_A;

Author:  ElEctric_EyE [ Tue Feb 28, 2012 2:03 am ]
Post subject: 

I am trying to do much at once, especially with disturbances at work where I cannot focus on the code, although I do think about the code when working...

I ran a Sim and values are changing but not as expected. I will back up a few steps for Acc to Acc transfer opcodes... I should be able to post progress soon with the tools I have learned so far on ISim and your advice.

Author:  Arlet [ Tue Feb 28, 2012 6:36 am ]
Post subject: 

ElEctric_EyE wrote:
Code:
                16'b0000_00xx_1011_1011:   // TBA
            dst_reg <= SEL_B;



No, the source is B, the destination is A. So you should set dst_reg to SEL_A, and src_reg to SEL_B

Author:  ElEctric_EyE [ Tue Feb 28, 2012 6:59 pm ]
Post subject: 

Ok, finally got through my thick skull!

All Acc to Acc transfers appear to be working. :D

Code:
$01BB...TAB     $009B...TBA     $00AB...TCA     $00BB...TDA
$02BB...TAC     $02AB...TBC     $01AB...TCB     $019B...TDB
$03BB...TAD     $03AB...TBD     $039B...TCD     $029B...TDC


Will do more testing to be sure...

And do a speed test tonight if all goes well.

EDIT: I couldn't wait. It passes with a O2 constraint @ 10.5ns for 95MHz. Now I'll continue testing...

Author:  ElEctric_EyE [ Wed Feb 29, 2012 2:42 pm ]
Post subject: 

I was close. But after a couple cups of coffee on a fresh day (away from work), I got it 100% correct. A few of the transfers were not working, but they are all working now. I had to put TAA TBB TCC TDD in the code (even though the commands are useless) to get my logic straight. Here are the new opcodes. Posted on Github.

I have almost completed what I set out to do with this core according to the header of this thread. I have yet to add a Z index register, but there are a few things I would like to do next...

There are 6 bits left for the transfer opcodes. It would be useful I think to use 2 of the bits and have 4 logic functions (AND, OR, EOR, NOT) built into an Acc-Acc transfer. I think this should still take 2 cycles and shouldn't be too hard to code for and shouldn't slow down the core speed if I understand correctly.
Code:
$008B...TAA     $009B...TBA     $00AB...TCA     $00BB...TDA
$018B...TAB     $019B...TBB     $01AB...TCB     $01BB...TDB
$028B...TAC     $029B...TBC     $02AB...TCC     $02BB...TDC
$038B...TAD     $039B...TBD     $03AB...TCD     $03BB...TDD

Author:  ElEctric_EyE [ Wed Feb 29, 2012 7:02 pm ]
Post subject: 

An index register and adding logic to the transfer opcodes are not as easy as I thought and I grow weary of Verilog.

I'm going to take this core now and work with it on the DevBoard.

Author:  ElEctric_EyE [ Thu Mar 01, 2012 8:55 pm ]
Post subject: 

Back at work again and things are slow, so I thought I would tackle the 'transfer with logic' again with the new accumulators.

I realized I needed a separate register that would contain the result of the logic functions AND, OR, XOR amongst the 4 Accumulators. The opcode names look like TABand, TABor, TABxor etc. in my As65 Macro's.

So this register called LOGOP (Logic Operator) I have working already with TABand and it takes 2 cycles. It may take 1 or more cycle to transfer it to the src_reg or dst_reg. Transferring this value will be the challenge for me at this point... I just finished all the other 4 Acc transfer + Logic.

If in the end these 'transfer with logic' opcodes slow down the core too much, I'll probably remove them. I am always concerned with speed, so we will see if a speed sacrifice is worth it, compared to cycles saved per instruction. I intend to focus on this tradeoff, during this 65Org16.b Core expansion. If they prove good speedwise, then I'll look how to do the same 'transfer with logic' opcodes between the X & Y index registers, stack, and 4 accumulators.
Been thinking recently too, there needs to be a single cycle 16bit NOT (i.e. inverse) on any accumulator/index register.
Code:
always @(posedge clk)
     if( state == DECODE && RDY )
     casex( IR[15:0] )
      16'b0000_xx01_1000_1011,   // TABand, TABor, TABxor
      16'b0000_xx00_1001_1011:   // TBAand, TBAor, TBAxor
      case( IR[11:10] )
         2'b01: LOGOP <= ( DCBAXYS[SEL_A] & DCBAXYS[SEL_B] );
         2'b10: LOGOP <= ( DCBAXYS[SEL_A] | DCBAXYS[SEL_B] );
         2'b11: LOGOP <= ( DCBAXYS[SEL_A] ^ DCBAXYS[SEL_B] );
     endcase
      default:case( IR[11:8] )
         4'b0001: LOGOP <= DCBAXYS[SEL_B]; //no LOGOP, send value to dest_reg
         4'b0000: LOGOP <= DCBAXYS[SEL_A]; //no LOGOP, send value to dest_reg
      endcase
   endcase


Still working on the total opcode value list. Will post when they're all proven on Isim.

Author:  Arlet [ Fri Mar 02, 2012 8:00 am ]
Post subject: 

Code:
LOGOP <= ( DCBAXYS[SEL_A] & DCBAXYS[SEL_B] );

If you do that, you'll make the register file multi-ported, which will explode its size. It's better to try to fit the logic operators inside the normal path. This would require 3 cycles for the 'TABand' instruction:

1. read A (src_reg)
2. read B (dst_reg)
3. write B (dst_reg)

cycles 1 and 3 are already needed for the regular TAB instruction, so you need to add a cycle in the middle. This is a new one, so it requires an update to the state machine, and it requires an extra MUX in the register file access so you can read from dst_reg. The alternative is to do this:

1. read A (src_reg), src_reg <= B
2. read B (src_reg)
3. write B (dst_reg)

This avoids the extra MUX, but requires an extra write to src_reg.

Anyway, this change is not as straightforward as earlier changes, since register/register operations aren't natural to the 6502. Maybe you should try to come up with something simpler to do first, to get some more experience.

A simpler, but quite powerful, extension to the opcode space is what I've mentioned earlier, which is to allow the source and destination Acc to be different. This does not allow Acc-Acc operations, but it does allow things like ADC A, #10 and store the result in B, with a full set of addressing modes and operands. All this requires is an extra 2 bits in the opcode to designate the destination register, and a few lines of Verilog.

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