The Raptor-16 Microprocessor Assembler looks and acts just like a static RAM for simulation, the main difference is that instead of it containing a pre-set content, it reads an assembly source file, compiles it and uses that to make up its content. Once compiled, the RAM content is written out to a number of Xilinx RAM files (CoreGen & initialized VHDL) that can then be used during the implementation phase to initialize the Block RAM's that make up the embedded (on-chip) memory.
It is entirely up to the user whether they want to simulate the Raptor-16 with the compiled source code or just use the Assembler to create the Xilinx RAM content file and then test the compiled code in hardware.
Although the Assembler does not offer all the features of commercial packages, it can detects and report syntax errors, provide warnings about optimizations and also produce binary listings. All these
options are controlled by constants in the Behavioural VHDL.
Below are some brief details of things that are not fully covered by the examples in the
Instruction Set.
Numbers are used for both instructions and data and can be represented in three different forms; binary, decimal and hexadecimal.
- Binary numbers start with a percent sign and are followed by 1's and 0's.
- Decimal numbers start with a number and are followed by other numbers.
- Hexadecimal numbers start with a dollar sign and are followed by 0-9 and A-F characters.
All number representations are extended by the Assembler to a full 16-bit value. Negative numbers can be used by adding a minus sign on the front of decimal number, however this is not allowed for Binary and Hexadecimal. To create a negative Binary or Hexadecimal number the full 16-bit value should be written in 2's compliment form.
Examples:-
|
Move |
#2048,SP |
; Positive decimal number |
|
LoadQ |
#-70,A0 |
; Negative decimal number |
|
Move |
$30(A4),D0 |
; Positive hexadecimal number |
|
MoveQ |
#$FFFF,D5 |
; Negative hexadecimal number |
|
AndQ |
D0,%011(A3) |
; Positive binary number |
|
And |
#%1000000100000011,D0 |
; Negative binary number |
|
|
Bytes |
255, -128, 127, $FF, %11001100, 65, $55, %100 |
|
Words |
%11, $A, $00FF, 3, -32000, %0001, $FFFF, 45 |
Data is created by using two commands; bytes and words, that define 8-bit and 16-bit values respectively. Both commands are used in exactly the same way and can be followed by any number of values separated by commas.
The bytes command supports an additional text string mode that can be used to create strings of text. Defining these strings is simply done by enclosing them in quotes. The bytes command does have a word-alignment restriction, that means an even number of bytes must follow the command.
The words command supports a additional pointer mode that can be used to create pointers within data. These pointers can point to anything that is labelled in the source code, be it code or other data.
Examples:-
SomeText |
Bytes |
"Hello World!", 13, 10, 0, 0 |
; A string of text |
SomeData |
Bytes |
10, 20, 35, 64, 77, 84 |
; A sequence of bytes |
NewText |
Bytes |
"Hello",13,"There",13,0,0 |
; A mixed byte sequence |
|
Wordy |
Words |
$FFFF, $FFFE, 55, 65 |
; A sequence of words |
Something |
Words |
40, -50, SomeText, -65 |
; A mixed word sequence |
Labels are used to mark lines in source code, that can then be referenced by instructions or data. A label is made up of alphabetical characters only and when used to mark a line must start on the very first character of that line. Referencing a label is simply achieved by using its name. The only restriction labels have is when they are used to mark lines, in this case they must be followed by either an instruction or data.
Working Example:-
DoStack |
Move |
#2048,SP |
; Set-up Stack Pointer |
|
Caller |
LoadQ |
#List,A0 |
; Get address of data labelled by 'List' |
|
Move |
Length(PC),D0 |
; Get data from location labelled by 'Length' |
|
BsrQ |
Average |
; Branch to subroutine labelled by 'Average' |
|
Infinite |
BraQ |
Infinite |
; Something useful would go here... |
|
Average |
MoveQ |
#0,D1 |
; Set total to 0 |
Loop |
Add |
(A0)+,D1 |
; Add list element to total |
|
SubQ |
#1,D0 |
; Decrement length |
|
BraQ |
zrc,Loop |
; Branch to location labelled by 'Loop' if length > 0 |
|
ShrQ |
#1,D1 |
; Half total to get average |
|
Rts |
|
; Return |
|
List |
Words |
3, 406, 44, 60, 55, 10 |
Length |
Words |
6 |
Commas are used to separate instruction operands and data values and can have any number of spaces before and after them, including none at all. The only restriction commas have is that something must follow them, unless they are inside a comment block.
Comments are used typically to describe code or to prevent code from being compiled. A comment can be inserted anywhere within the source code and is started with a semi-colon. The Assembler ignores everything that follows a semi-colon up to the end of the line where it appears. The only restriction comments have is when they follow instructions or data, at least one space must separate the end of an instruction or data from the start of a comment.
Working Example:-
|
Move |
#2048,SP |
; Set-up Stack Pointer |
|
|
LoadQ |
#DataA,A0 |
; Set A0 to point to array 1 |
|
LoadQ |
#DataB,A1 |
; Set A1 to point to array 2 |
|
BsrQ |
Adder |
; Branch to add routine |
|
|
; Something useful would go here... |
|
Infinite |
BraQ |
Infinite |
; Repeat forever |
|
; Add together the values from two arrays and return the result in D0. |
; A0 contains the pointer to array 1 and A1 contains the pointer to array 2. |
; Both pointers are incremented by the subroutine ready for the next call. |
|
Adder |
Move |
(A0)+,D0 |
; Get value from array 1 and increment its pointer |
|
Add |
(A1)+,D0 |
; Add value from array 2 and increment its pointer |
|
Rts |
|
; Return from subroutine |
|
;Adder |
Move |
(A0)+,D0 |
; This code will not be compiled |
; |
Add |
(A1)+,D1 |
; This code will not be compiled |
; |
Rts |
|
; This code will not be compiled |
|
DataA |
Words |
302, 12, 59 |
; Array 1 Data |
DataB |
Words |
100, 332, 1045 |
; Array 2 Data |
The Raptor-16 Assembler (assembler.vhd) contains a number of options that can be changed by the user, these are described below.
Option |
Description |
assembly_file |
Sets the filename of the source code that is to be compiled by the Assembler. |
sp2_file |
Sets the filename of the Xilinx Spartan 2/2E initialized Block RAM VHDL that will be created by the Assembler. |
sp3_file |
Sets the filename of the Xilinx Spartan 3 initialized Block RAM VHDL that will be created by the Assembler. |
source_path |
Sets the location where the Xilinx Spartan 2/2E & 3 initialized Block RAM VHDL files will be written. |
coe_file |
Sets the filename of the Xilinx CoreGen RAM Content (COE) that will be created by the Assembler. |
xco_file |
Sets the filename of the Xilinx CoreGen RAM Configuration (XCO) that will be created by the Assembler. |
coregen_path |
Sets the location where the Xilinx CoreGen RAM files will be written. |
ram_size |
Sets the size of the RAM that is to be used to contain the compiled source code. This must be either 256, 512, 1024, 2048 & 4096, 8192, 16384, 32768 or 65536. |
max_label_entries |
Sets the maximum number of labels that can be used in the source code. |
max_label_length |
Sets the maximum number of characters that a label can have. |
max_code_lines |
Sets the maximum number of lines that the source code can have. |
max_code_length |
Sets the maximum character length that a source code line can be. |
debug_msg |
When TRUE the Assembler will display the binary listing as it compiles the source code. |
opt_msg |
When TRUE the Assembler will display all source code optimizations it finds. |