6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Apr 28, 2024 10:40 pm

All times are UTC




Post new topic Reply to topic  [ 353 posts ]  Go to page Previous  1 ... 15, 16, 17, 18, 19, 20, 21 ... 24  Next
Author Message
 Post subject: Re: 65ORG16.b Core
PostPosted: Sat Apr 21, 2012 8:31 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Ok, I got it working, but you have something similar to this in your code BigEd :
Code:
always @*   
   case( state )   
      DECODE: write_streg <= load_streg;       
      default: write_streg <= 0;   
   endcase

and then this:
Code:
always @(posedge clk )     
   if( write_streg & RDY )       
   STACKPAGEReg <= DIMUX;


Using this alone appears to work:
Code:
always @(posedge clk )     
   if( load_streg & RDY )       
   STACKPAGEReg <= DIMUX;

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sat Apr 21, 2012 9:19 pm 
Offline

Joined: Thu Mar 15, 2012 4:00 am
Posts: 5
EE:

I've been folllowing your discussions on this thread for a while, but I've not delved into any of the code. However, in your last post/reply, I think that you've reduced the code beyond what BigEd appeared to intend. That is, the following code fragment is more in the spirit that BigEd appears to intend:
Code:
assign WE = (state == DECODE) & load_streg & RDY;

always @(posedge clk)
begin
     if(WE)
          STACKPAGEReg <= DIMUX;
end

Your implementation of the always block does not appear to consider that BigEd's write_streg is only asserted when (state == DECODE) and load_streg is asserted. In your implementation, this additional qualification of the write enable of the STACKPAGEReg may not be required, and if so, please ignore this reply. You are correct, however, that BigEd's code may have been more legibly expressed as:
Code:
always @(*) write_streg <= (state == DECODE) & load_streg;

In this manner, no case statement with a default expression is required.


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sat Apr 21, 2012 9:42 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Hi Michael, you're correct I said it worked without some more vigorous testing, I was about to delete the post... But thanks for replying! In this register, I don't care if it's a read or write. I just need the data following the opcodes that trigger load_streg and load_zpreg to go into the registers. I do this because the opcodess are basically just a transfer instruction. Still working on it.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sat Apr 21, 2012 10:21 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
I confess that my B and D reg code is just copied from the nearby regfile code without much thought - it is possible that it can be simplified. It does look like load_b_reg is in fact only valid at decode and rdy.

Note that the code might need to take the existing form if instead of two or more zero-operand opcodes we had a one-operand opcode as I suggested at one point, picking up the special register address from the data bus in a later cycle. I'm not certain of this. I find it all rather difficult!

Edit: hmm, that might not make sense, in which case I apologise for posting while tired. I've got XBA and TXD which are both zero operand. XSR #reg would be one operand.

Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sat Apr 21, 2012 11:44 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Ed you are onto why I had my problem originally.
BigEd wrote:
...Note that the code might need to take the existing form if instead of two or more zero-operand opcodes we had a one-operand opcode as I suggested at one point, picking up the special register address from the data bus in a later cycle. I'm not certain of this. I find it all rather difficult!

I believe you had the same problem I initially had... I had defined the new opcodes in the state machine for REG only. Now I have those opcodes defined for REG and FETCH, which is used for opcodes in immediate mode, like LDA #$xxxx, etc. Now I have something that works! But alot more has changed as well. First for simulation purposes, I had to initialize load_zpreg and load_streg to 0. Some changes to your code (only changes shown):
Code:
always @*   
   case( state )   
      FETCH: write_zpreg <= load_zpreg;       
      default: write_zpreg <= 0;   
   endcase
   
always @*   
   case( state )   
      FETCH: write_streg <= load_streg;       
      default: write_streg <= 0;   
   endcase   

Then this code to write to the registers:
Code:
always @(posedge clk )     
   if( write_zpreg & RDY )       
   ZEROPAGEReg <= DIMUX;

always @(posedge clk )     
   if( write_streg & RDY )       
   STACKPAGEReg <= DIMUX;


I will do more testing, but intial testing is proving OK!

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 12:58 am 
Offline

Joined: Thu Mar 15, 2012 4:00 am
Posts: 5
Ed:

I appreciate you linking your code for me in your last post. I had this nice reply in the works and then I decided to click through to your code for a second look, and when I got back, my tome was lost. So I will try and reconstruct it as best I can.

Your code is very clean, and clearly follows the structure and style of Arlet Ottens. Like most members of this forum, I am also working on an FPGA implementation of the WDC 65C02. I have currently completed one one core and am working on my second. My general objectives are a faithfull reproduction of the WDC 65C02 instruction set, but not necessarily the instruction cycle time. Actually, my objective in that regard is to reduce the number of clock cycles required for most instructions without resorting to using a wider data bus. My approach to the implementation of the core also differs from those that others such as yourself, and Arlet Ottens have posted. That is, I use a microprogrammed instruction sequencer.

My first core was intended to be used with a single cycle asynchronous memory such as can be synthesized from Xilinx LUTs. It assumes that the address is output and the data is returned on the same cycle. At the performance that I was targeting, 100 MHz in a Xilinx XC3S200AN-5, this approach is not particularly practical since any reasonable program would require too much of the free LUTs and would not provide a sufficiently large memory for anything but toy applications. My second core is a more complete implementation with BRAM included in the core. The difference in the access method has caused me to rethink some of the asynchronous logic that I used for single cycle address calculation in the first core. Without considering the delays in the address output path or the input data path delays (as is the case in functional simulation), my first attempt is complete. But it will never work in a practical system. Thus, the second core has been derived from the first core, and it deals with these practical considerations. With respect to the second core, I have completed its re-implementation and reworked the microprogram's control fields, but I've not yet begun to debug the microprogram. Given the amount of time that I have available to persue this hobby, its going to be several weeks before that task can be completed.

Back to your core. You and Arlet are using a one-hot state machine methodology for the instruction sequencer. I've not been much of a fan of the one-hot state machine approach for a number of reasons, although I often use one-hot control fields. However, the performance and resource utilization that Arlet achieved (as you detailed in an earlier post comparing various cores), coupled with the cleanliness of the implementation, has convinced me to put some effort to studying the methodology once I've completed my second core. It appears that the base design uses the register file to provide the AI input to the ALU module. I have used the LUT RAMs in the Xilinx FPGA in this manner for many years. The inherent multiplexer of the RAM is the fastest way to improve the operating speed of a Xilinx FPGA.

It also appears that the register file is implemented as a single port RAM and that the core does not use multiple, independent adders to provide parallel computation of addresses and/or ALU results. Therefore, I am going to suggest expanding the register file so that you can also use it for temporary storage instead of wiping out your S storage location. Since for the Xilinx FPGA that you are using, any use of a LUT as a single or dual port RAM will always make available a minimum of 16 "registers", the synthesizer is currently tying off the two (16) or four (64) most significant address lines. (I am sure that you are aware that Xilinx FPGAs older than the Spartan 6 and Virtex 7 families employ 4 input LUTs, while these two FPGA families employ 6 input LUTs.) In this manner, you can place your B register into the register file, and any other registers or temporary values that you be need. I don't think that this suggestion applies to the shift count/direction register, but I've not spent any time exploring the implementation or the instruction set that you are presently implementing with your core.

Once again, thanks for the link to your code.

BTW, you need not modify the present definition of the regfile address/select variable: "regsel". You can simply extend it using a bit vector construction, {extreg, regsel}, where "extreg" is declared as a 2-bit or a 4-bit vector (set by the FPGA family that you are using). If you fail to include the expanded RAM select vector when addressing the register file, then verilog's default behavior will left fill the RAM address with 0s, and the register file will behave like your current implementation: a four location RAM. (A synthesizer or PAR warning should be issued, and it will indicate that the RAM address is zero filled because its not completely specified.)


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 1:50 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
What exactly is your contribution to the subject matter at hand? I don't follow? Not 100% OT but it's headed there.

Maybe you should start a new thread here in the Programmable Logic section on your endeavours.

What I mean to say is, if you are some kind of expert, then let's see your projects then, some evidence or proof, some kind of project, which we people always demand.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Last edited by ElEctric_EyE on Sun Apr 22, 2012 1:55 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 1:55 am 
Offline

Joined: Thu Mar 15, 2012 4:00 am
Posts: 5
Sorry about that.


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 1:58 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Listen, I don't mean to get all negative, but we were trying to achieve a common goal of a relocatable zero page and stack for the 65Org16... We do welcome experts!! Maybe post here one of your Verilog projects?

Or even better, post your intro in the Introduce Yourself, under the General Discussion section, then at least we can all know where you're coming from. BTW welcome Alabama!

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 7:02 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
What kind of opcode(s) are you using to set the new registers ?

At first I thought you were using some sort of Txx opcode, but now I see you using the FETCH state, so I'm confused. Are you now using something like LDA IMM ?


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 7:40 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
I guess it is more like a 'load' opcode at this point. I've name them ZPR and STR for zero page register/relocate and stack register/relocate.

It would be ideal to be able to transfer a value from any accumulator/register, but there are no src_reg, dst_reg.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 8:20 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
ElEctric_EyE wrote:
It would be ideal to be able to transfer a value from any accumulator/register, but there are no src_reg, dst_reg.

A simple trick is to use a shadow register in the register file. If you don't mind sacrificing a register, you could use one of the existing registers, like you tried before. Let's say you define 'Z' to be your zero page register. To avoid making the register file multi-ported, you add an extra '[15:0] zp_reg', and whenever you write the Z register, you write zp_reg with the same value:
Code:
always @(posedge clk)
    if( write_register & RDY & (regsel == SEL_Z) )
       zp_reg <= ADD;

And then you can simply use the zp_reg instead of ZEROPAGE in the AB signal.

Now, if you don't need the full set of operations on the Z register, and you don't want to waste a register in the register file you can make special register file entries. To do that, you extend the register file from 16 to 32, and define SEL_ZP as 16. Other special registers can be numbered 17..31. Also, src_reg/dst_reg/regsel need to be adjusted to 5 bits. Now, whenever you see your new TxZP opcode (transfer from regular register to ZP), set dst_reg <= SEL_ZP, and when you see the TZPx, set src_reg <= SEL_ZP.


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 8:49 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Actually, you could generalize this method:
  • Extend register file to 32 entries.
  • Use registers 0..15 like you've been doing so far, with 4 bits in the opcode to designate src and/or dst register.
  • Use two special transfer opcodes. They work exactly the same as the regular TAX, TXS, etc opcodes, except one of them sets the high bit in src_reg, and the other opcode sets the high bit in the dst_reg.
Using the special transfer, you can move data from any of the 'low' 16 registers to the 'high' 16 registers, and back. By using the shadow register method, each one of those registers can have a special function. The registers that don't need a special function can be used as temporary storage.


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 9:29 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
MichaelA wrote:
Sorry about that.

Michael, I very much appreciate your posting - I've started a new thread to continue a more general discussion.
Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject: Re: 65ORG16.b Core
PostPosted: Sun Apr 22, 2012 2:27 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
My apologies to MichaelA for being so abrasive earlier. There's no explanation for it, except to say I was up at very early hours. It would be great to have more talent present here!

Arlet wrote:
...Now, if you don't need the full set of operations on the Z register, and you don't want to waste a register in the register file you can make special register file entries. To do that, you extend the register file from 16 to 32, and define SEL_ZP as 16. Other special registers can be numbered 17..31. Also, src_reg/dst_reg/regsel need to be adjusted to 5 bits. Now, whenever you see your new TxZP opcode (transfer from regular register to ZP), set dst_reg <= SEL_ZP, and when you see the TZPx, set src_reg <= SEL_ZP.

I thought involving the regfile, any part of it, in modifying stack page and zero page pointers would make it a 3 ported RAM? My regsel is already up to 5 bits, as I have 16 accumulators, the 3 index registers and the stack register.

BTW, I am at home today, so I can roll back some recent changes and do some comparative speed tests. That is if ISE cooperates!

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 353 posts ]  Go to page Previous  1 ... 15, 16, 17, 18, 19, 20, 21 ... 24  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: