Monday, November 14, 2011

A 54 Bit Counter

I have a need for a 54 bit counter for a project I'm planning. I need to count an accurate clock without any overflows. Now I admit that at my designed 4.8 MHZ the clock will overflow in 100+ years. If the device is never turned off. Power outages alone ought to reset it oftener than that. What is the device I'm designing? Stay tuned.

Here is a screenshot of the program.


I'm going to go through it line by line using "old" Forth notation where ":" means start a subroutine and ";" means Return (it also means Return in colorForth). In my notation scheme "\\" is the start of a comment. All numbers beginning with an "0x" are hexidecimal. Otherwise they are decimal. This is to make up for the lack of color in normal text display. Since this is for novices I'm going to explain everything on a word by word basis (mostly).

Update: 16 Nov 2011 1822z

The terminology I used below (TOS and NOS for Top Of Stack and Next On Stack) is not in use by GreenArrrays. They are old Forth terms. Green Arrays uses "T" for Top and "S" for Second.

It should also be noted that @p increments the program counter immediately but the program does not go to the next address in the Program Counter until all the slots in a word have executed. Thus you can have constructs in one word such as "@P @P @p ." which is three literals in a row. When executed it puts 3 literals on the stack and increments the program counter three times.

===
user f18 code   // a comment

reclaim         // free up previously used words in the
                // non-core dictionary

100 node 0 org  // the code loads in node 100 at location 0

: zero          // this is a place holder for the compiler
                // no code is compiled

0x0d org        // this is where the counter gets placed
                // it uses 3 locations (54 bits) 

: new-count     // a place holder

0 , 0 , 0 ,     // notice that the yellow color indicates we 
                // are in the interpreter the "," means put 
                // what is on the stack, "0" in this case,
                // at the current location

0x1a org        // old count goes here

: old-count     // a place holder

0 , 0 , 0 ,     // notice that the yellow color indicates we 
                // are in the interpreter the "," means put 
                // what is on the stack, "0" in this case,
                // at the current location

0x1 org +cy     // load at location 1,  +cy translates the 
                // location so that the carry bit is used

: inc-counter   // this subroutine will increment the counter 
                // every time it is called

@p              // fetch word at program counter +1, put it on 
                // the top of the stack (TOS), skip over the 
                // word to execute the next instruction

a!              // put the TOS in "a" register

..              // go to next word with no-ops - as many as 
                // needed

'               // in the interpreter (host) find the target 
                // address of the following subroutine and 
                // put it on the interpreter stack 

new-count       // word to find in the target address space

,               // put the host TOS in the next available 
                // target address 

clc             // clear carry - routine located in the ROM

@               // fetch to the TOS via "a" which now has the 
                // address of new-count in it  - which is to 
                // say get the low order of the count

0x20000         // we are going to add this to the count.
                // normally this number would be 1 but we 
                // want to see carry propagating for testing 
                // purposes. We also could have initialized 
                // the counter to different values for testing

.               // nop - this delay allows the add to 
                // complete before the result is needed 

+               // add the TOS (increment value) to the next 
                // on stack (NOS) (previous counter low order 
                // value)

!+              // store TOS (incremented value) at "a" and 
                // increment "a" 

0x0             // put a zero on top of the stack 

dup             // push the TOS into the NOS, TOS is unchanged

@               // fetch using the "a" register as a pointer

.               // wait to help + complete in time

+               // add the counter middle value to the 0 on 
                // the stack which is to say – propagate the 
                // carry

!+              // save it to address pointed to by "a" (back 
                // where it came from)

@               // fetch using the "a" register as a pointer

.               // wait to help + complete in time

+               // add the counter top value to the 0 on the
                // stack which is to say – propagate the carry

!               // save it to address pointed to by "a" (back 
                // where it came from) do not increment "a" 

zero ;          // this is how you force a jump – a call 
                // followed by a return  - as far as the 
                // compiler knows "zero" is located at 0x0 
                // this will force a jump to 0x0

-cy             // we don't care about the carry anymore

0x0 org         // the next word goes here

: beginner      // we are starting a new word at location 0x0

inc-counter ;   // this jumps to inc-counter

reclaim         // the subroutines created are specific to 
                // this module (local)

After you have entered the program "save" it. Don't forget that Screen 148 must point to "100". Now you can start the simulator

Update: 14 Nov 2011 1731z

I corrected a discrepancy between the screen shot and the listing below it. The screen shot was wrong ("+" missing), The correct screen is now in place. Thanks to commenter forther.

3 comments:

  1. IMHO you forgot to propagate the carry into highest counter's word.

    ReplyDelete
  2. You are correct I diddled with the working version and obviously messed something up. I'll fix it.

    ReplyDelete