circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

March 2000, Issue 116

Building a RISC System In AN FPGA Part 1:
Tools, Instruction, Set and Datapath


INSTRUCTION SET

Now, let’s refine the instruction set and choose an instruction encoding. My goals and constraints include: cover C (integer) operator set, fixed-size 16-bit instructions, easily decoded, easily pipelined, with three-operand instructions (dest = src1 op src2/imm), as encoding space allows. I also want it to be byte addressable (load and store bytes and words), and provide one addressing mode—disp(reg). To support long ints we need add/subtract carry and shift left/right extended.

Which instructions merit the most bits? Reviewing early compiler output from test applications shows that the most common instructions (static frequency) are lw (load word), 24%; sw (store word), 13%; mov (reg-reg move), 12%; lea (load effective address), 8%; call, 8%; br, 6%; and cmp, 6%. Mov, lea, and cmp can be synthesized from add or sub with r0. 69% of loads/stores use disp(reg) addressing, 21% are absolute, and 10% are register indirect.

Therefore we make these choices:

• add, sub, addi are 3-operand
• less common operations (logical ops, add/sub with carry, and shifts) are 2-operand to conserve opcode space
• r0 always reads as 0
• 4-bit immediate fields
• for 16-bit constants, an optional immediate prefix imm establishes the most significant 12-bits of the instruction that immediately follows
• no condition codes, rather use an interlocked compare and conditional branch sequence
• jal (jump-and-link) jumps to an effective address, saving the return address in a register
• call func encodes jal r15,func in one 16-bit instruction (provided the function is 16-byte aligned)
• perform mul, div, rem, and variable and multiple bit shifts in software

The six instruction formats are shown in Table 2 and the 43 distinct instructions are shown in Table 3. adds, subs, shifts, and imm are uninterruptible prefixes. Loads/stores take two cycles, jump and branch-taken take three cycles (no branch delay slots). The four-bit imm field encodes either an int (-8–7): add/sub, logic, shifts; unsigned (0–15): lb, sb; or unsigned word displacement (0, 2–30): lw, sw, jal, call.

Format

rrr
rri
rr
ri
i12
br

15–12

op
op
op
op
op
op

11–8

rd
rd
rd
rd
imm12
cond

7–4

ra
ra
fn
fn

disp8

3–0

rb
imm
rb
imm

Table 2—The xr16 has six instruction formats, each with 4-bit opcode and register fields.

 

Hex

0dab
1dab
2dai
3d*b
4d*I


5
dai
6dai
8dai
9dai
Adai
B*dd

C
iii
Diii
7xxx
E
xxx
Fxxx

Fmt

rrr
rrr
rri
rr
ri


rri
rri
rri
rri
rri
br

i12
i12


Assembler

add rd,ra,rb
sub rd,ra,rb
addi rd,ra,imm
{and or xor andn adc
sbc} rd,rb
{andi ori xori andni
rd = rd op imm;
adci sbci slli slxi
srai srli srxi} rd,imm
lw rd,imm(ra)
lb rd,imm(ra)
sw rd,imm(ra)
sb rd,imm(ra)
jal rd,imm(ra)
{br brn beq bne bc bnc bv
bnv blt bge ble bgt bltu
bgeu bleu bgtu} label
call func
imm imm12
reserved
reserved
reserved

Semantics

rd = ra + rb;
rd = ra – rb;
rd = ra + imm;
rd = rd op rb;




rd = *(int*)(ra+imm);
rd = *(byte*)(ra+imm);
*(int*)(ra+imm) = rd;
*(byte*)(ra+imm) = rd;
rd = pc, pc = ra + imm;

if (cond) pc += 2*disp8;
r15 = pc, pc = imm12<<4;
imm'next15:4 = imm12;

Table 3—The xr16 needs only 43 different instructions to efficiently implement an integer-only subset of the C programming language.

Some assembly instructions are formed from other machine instructions, as you can see in Table 4. Note that only signed char data use lbs.

Assembly

nop
mov rd,ra
cmp ra,rb
subi rd,ra,imm
cmpi ra,imm
com rd
lea rd,imm(ra)
lbs rd,imm(ra)
(load-byte,
sign-extending)
j addr
ret

Maps to

and r0,r0
add rd,ra,r0
sub r0,ra,rb
addi rd,ra,-imm
addi r0,ra,-imm
xori rd,-1
addi rd,ra,imm
lb rd,imm(ra)
xori rd,0x80
subi rd,0x80
jal r0,addr
jal r0,0(r15)

Table 4—Many assembly pseudo-instructions are composed from the native instructions. Only rare signed char data use the rather expensive lbs.