Giter Club home page Giter Club logo

manning-softcpu's Introduction

16 bit processor in VHDL

This is a project for self-learning, and is pretty much useless except for anyone interested in how a simple processor could be implemented. That said, I think it's cool.

This is of course a work in progress.

Summary of features

  • 16 bit address and databuses
  • 16 bit opcodes
  • Byte and word size memory accesses, with signed/unsigned extension on byte reads
    • Bus error signal on unaligned word transfers
  • Some opcodes (like LOADI, JUMPs, BRANCHes, ALUMI, CALLs) have one following immediate value/address
  • 8 x 16 bit general purpose registers
  • 16 bit Program Counter
  • Load an immediate 16 bit quantity at the following address
  • Load and store instructions operate either through a register, an immediate address or a register with an immediate displacement
  • Clear instruction
  • Simple status bits: zero, negative, carry
  • ALU operations including
    • add, add with carry, subtract, subtract with carry, signed and unsigned 8 bit to 16 bit multiply, increment, decrement, and, or, xor, not, shift left, shift right, copy, negation, etc
  • ALU operations are of the form DEST <= DEST op OPERAND, or DEST <= op DEST
    • ALUMI operates with an immediate operand, eg. add r0,#123
  • Conditional and uncoditional jumps and branches: always, on each flag set or clear with don't cares
  • Nop and Halt instructions
  • Stacking: call/return and push and pop
  • No microcode: a coded state machine is used
  • Most instructions take 3 cycles
  • CustomASM (https://github.com/hlorenzi/customasm) is the current assembler

TODO

  • Interrupts, including software traps
  • Testbench for the controller
  • Add more instructions!
    • Relative addressing on loads and stores with the PC
    • (Better) multiply and divide?
    • Barrel shifter?
    • Restricting ALU ops to byte wide values might be useful
    • ....
  • Better status bits: not currently settable via an opcode, nor are they changed on anything other then an ALU instruction
    • This unfortuantely includes the LOADRD and STORED opcodes, which is confusing and wrong
  • It should be possible to do a build without multiply support, as very small FPGAs will not have sufficent resources

Top level RTL diagram (OUT OF DATE)

Top level RTL

Opcode map

Opcode 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
NOP 0b000000 -
Do nothing
JUMP 0b000010 - Flag cares Flag polariy
If (Flags AND Flag cares = Flag polarity) then PC ← IMMEDIATE
BRANCH 0b000011 - Flag cares Flag polariy
If (Flags AND Flag cares = Flag polarity) then PC ← PC + IMMEDIATE
CLEAR 0b001100 - Reg
Reg ← 0
LOADI 0b000100 Byte Signed - Dst reg
Dst reg ← IMMEDIATE
LOADM 0b001000 Byte Signed - Dst reg
Dst reg ← [IMMEDIATE]
STOREM 0b001001 Byte Signed -Src reg
[IMMEDIATE] ← Src reg
LOADR 0b001010 Byte Signed - Src addr reg Dst reg
Dst reg ← [Src addr reg]
STORER 0b001011 Byte Signed - Dst addr reg Src reg
[Dst addr reg] ← Src reg
LOADRD 0b011010 Byte Signed - Src addr reg Dst reg
Dst reg ← [Src addr reg + IMMEDIATE]
STORERD 0b011011 Byte Signed - Dst addr reg Src reg
[Dst addr reg + IMMEDIATE] ← Src reg
ALUM 0b001110 ALU multi op Operand reg Dst reg
Dst reg ← Dst reg ALU mlti op Src reg
ALUS 0b001111 ALU single op - Dst reg
Dst reg ← ALU single op Dst reg
ALUMI 0b011000 ALU multi op - Dst reg
Dst reg ← Dst reg ALU multi op IMMEDIATE
CALLJUMP * 0b010000 - Stack reg Stack reg
Stack reg ← Stack reg - 2 ; [Stack reg] ← PC ; PC ← IMMEDIATE
CALLBRANCH 0b010001 - Stack reg Stack reg
Stack reg ← Stack reg - 2 ; [Stack reg] ← PC ; PC ← PC + IMMEDIATE
RETURN 0b010010 - Stack reg Stack reg
PC ← [Stack reg] ; Stack reg ← Stack reg + 2
PUSHQUICK 0b010100 - Stack reg Src reg
Stack reg ← Stack reg - 2 ; [Stack reg] ← Src reg
POPQUICK 0b010101 - Stack reg Dst reg
Dst reg ← [Stack reg] ; Stack reg ← Stack reg + 2

Flag cares and flag polarity

2 1 0
Carry Zero Negative

Registers

0b000 r0
0b001 r1
0b010 r2
0b011 r3
0b100 r4
0b101 r5
0b110 r6
0b111 r7

ALU multi (destination and operand) operations

0b0000 Add
0b0001 Add with cary
0b0010 Subtract
0b0011 Subtract with cary
0b0100 Bitwise AND
0b0101 Bitwise OR
0b0110 Bitwise XOR
0b0111 Copy
0b1000 Compare
0b1001 Bitwise test
0b1010 Unsigned 8 bit to 16 bit multiply
0b1011 Signed 8 bit to 16 bit multiply
0b1100-0b1111 Unused

ALU single (destination only) operations

0b0000 Increment
0b0001 Decrement
0b0010 Double increment
0b0011 Double decrement
0b0100 Bitwise NOT
0b0101 Left shift
0b0110 Right shift
0b0111 Negation
0b1000 Byte swap
0b1001 Compare with zero
0b1010-0b1111 Unused

Sample code

The currently used CustomASM CPU definition makes it possible to write very presentable assembly by, for example, combing LOADI, LOADM, LOADR and LOADRD into a single "load" mnemonic with the width represented by .w, .bu or .bs. ALU operations are similarly represented.

; prints the messsge in r2 at row r0 coloumn r1

printmsg:       shiftleft r0                    ; word wide address so shift
                load.w r0,(rowoffsets,r0)       ; get the start of the row
                add r0,r1                       ; add the column
.loop:          load.bu r1,(r2)                 ; get the char
                test r1                         ; checking for null
                branchz printmsgo               ; done?
                store.b (r0),r1                 ; output the char
                inc r2                          ; move to next source char
                inc r0                          ; move to next video addr
                branch .loop                    ; get more
printmsgo:      return                          ; done

; polls the ps2 port for a byte, returning 0 in r0 if nothing is available

getps2byte:     load.bu r0,PS2_STATUS           ; get from the status reg
                test r0                         ; nothing?
                branchz .nothing                ; keep waiting yet....
                load.bu r0,PS2_SCANCODE         ; get the scancode
                compare r0,#0xf0                ; break?
                branchz .nothing                ; no, carry on
                store.w SEVENSEG,r0             ; display it for debug
                return                          ; done
.nothing:       clear r0                        ; return 0
                return                          ; done

manning-softcpu's People

Contributors

aslak3 avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.