Rapid Prototyping using a Microprocessor Core on a Spartan

Download Report

Transcript Rapid Prototyping using a Microprocessor Core on a Spartan

Rapid Prototyping using a
Microprocessor Core
on a Spartan II FPGA
Richard E. Haskell and Darrin M. Hanna
CSE Dept., Oakland University, Rochester, MI 48309
Proc. Int. Conf. on Embedded Systems and Applications
ESA’03, pp. 49-55
Las Vegas, Nevada, June 23-26, 2003
Rapid Prototyping using a Microprocessor Core
on a Spartan II FPGA
• A Digilent Prototyping Board
– Xilinx Spartan IIE FPGA
• The FC16 Forth Core
• Rapid Prototyping of the DIO2 Peripheral
Board
–
–
–
–
DIO2 buttons, LEDs, and 7-seg displays
Multiplication and Division
The Liquid Crystal Display
A Simple Decimal Calculator
• Summary
Digilab 2E – Spartan IIE
www.digilentinc.com
Digilab 2E – Spartan IIE
2.5VDC
regulator
50MHz
CLK
Push Status
button LED
SPROM
Expansion D
Serial
Port
EPP or SPP
parallel port
Xilinx Spartan2
XC2S200E-PQ208
Expansion C
RS-232
converter
3.3VDC
regulator
Buffer
Parallel Port
Serial Port
Power
jack
5-9VDC
JTAG
Port
Port/prog
control
switch
Expansion A
Expansion E
Expansion B
Expansion F
Digilab IO2 Board
•16x2 character LCD
•Four seven segment displays
•16 LEDs in three colors
•8 switches
•15 pushbutton keypad
•8-bit VGA port
•PS/2 port
Digilab IO2 Board
Connector A
2
GND
4
8
data
control
6
4
address
5VDC
regulator
JTAG
VU
Connector B
10
3
PS2
port
VGA
port
16x2
LCD
VDD
XC95108
PC84
4 7-seg.
displays
15 LEDs
8 switches
15 button
keypad
Connector A
4
8
data
6
4
control
5VDC
regulator
address
Accessing the
DIO2 Peripheral Board
2
GND
JTAG
VU
Connector B
10
3
PS2
port
VGA
port
16x2
LCD
VDD
XC95108
PC84
4 7-seg.
displays
cs
oe
we
addr(5:0)
data(7:0)
1
1
0
xxxx00
btns(7:0)
1
1
0
xxxx01
‘0’&btns(14:8)
1
1
0
xxxx1x
switchs
1
0
000100
leds(7:0)
1
0
000101
leds(15:8)
1
0
000110
sseg_reg(7:0)
1
0
000111
sseg_reg(15:8)
15 LEDs
8 switches
15 button
keypad
M
R
0
psel
The FC16
Forth Core
Pmux
P1
T
0
1
rinsel
Rmux 1
Rin
Pin
P(15:0)
pload
pinc
clr
clk
PC
plus1
P
rsel
rload
rdec
ReturnStack
clr
clk
rpush
rpop
E1(15:0)
S(1:8)
R
M(15:0)
M
y
M
irload
0
1
2
E1 E2
3
4
5
Tmux
clr
clk
IR
E2(15:0)
S
N2
6
N
7
tsel(2:0)
Tin
tload
icode
R
B(1:4)
T
clr
nload
nsel
ssel
clr
clk
dpush
dpop
DataStack
clk
oe
FC16_control
we
N2
cs
N
T
T(15:0)
digload
N(15:0)
LCD_RW
Funit16
LCD_RS
LCD_E
y1(15:0)
The FC16
Forth Core
Fcode(5:0)
y(15:0)
Tin(15:0)
DataStack
tload
The Data Stack
clr
clk
y1(15:0)
T1
y1
2
nsel(1:0)
ssel
N2
0
1
Nmux
Nin
nsel(1:0)
nload
tload
Treg
clr
clk
nload
Nreg
N1
T
0
clr
clk
dpush
dpop
Smux
1
ssel
d
clr
clk
dpush
dpop
stack32x16
full
empty
T(15:0)
N(15:0)
N2(15:0)
Data Stack Instructions
Hex Opcode
Name
Function
0000
NOP
No operation
0001
DUP
0002
SWAP
0003
DROP
0004
OVER
0005
ROT
0006
-ROT
0007
NIP
0008
TUCK
0009
ROT_DROP
000A
ROT_DROP_SWAP
Duplicate T and push data stack.
N <= T; N2 <= N;
Exchange T and N.
T <= N; N <= T;
Drop T and pop data stack.
T <= N; N <= N2;
Duplicate N into T and push data stack.
T <= N; N <= T; N2 <= N;
Rotate top 3 elements on stack clockwise.
T <= N2; N <= T; N2 <= N;
Rotate top 3 elements on stack counter-clockwise.
T <= N; N <= N2; N2 <= T;
Drop N and pop rest of data stack. T is unchanged.
N <= N2;
Duplicate T into N2 and push rest of data stack.
N2 <= T;
Drop N2 and pop rest of data stack. T and N are unchanged.
Equivalent to ROT DROP
Drop N2 and pop rest of data stack. T and N are exchanged.
Equivalent to ROT DROP SWAP
M
R
0
psel
The FC16
Forth Core
Pmux
P1
T
0
1
rinsel
Rmux 1
Rin
Pin
P(15:0)
pload
pinc
clr
clk
PC
plus1
P
rsel
rload
rdec
ReturnStack
clr
clk
rpush
rpop
E1(15:0)
S(1:8)
R
M(15:0)
M
y
M
irload
0
1
2
E1 E2
3
4
5
Tmux
clr
clk
IR
E2(15:0)
S
N2
6
N
7
tsel(2:0)
Tin
tload
icode
R
B(1:4)
T
clr
nload
nsel
ssel
clr
clk
dpush
dpop
DataStack
clk
oe
FC16_control
we
N2
cs
N
T
T(15:0)
digload
N(15:0)
LCD_RW
Funit16
LCD_RS
LCD_E
y1(15:0)
The FC16
Forth Core
Fcode(5:0)
y(15:0)
Funit16 Instructions (fcode = lower 6 bits of opcode)
Hex Opcode
Name
Function
0010
+
Pop N and add it to T.
0011
-
Pop T and subtract it from N.
0012
1+
Add 1 to T
0013
1-
Subtract 1 from T
0014
INVERT
Complement all bits of T.
0015
AND
Pop N1 and AND it to T.
0016
OR
Pop N1 and AND it to T.
0017
XOR
Pop N1 and AND it to T.
0018
2*
Logic shift left T.
0019
U2/
Logic shift right T.
001A
2/
Arithmetic shift right T.
001B
RSHIFT
Pop T and shift N1 T bits to the right.
001C
LSHIFT
Pop T and shift N1 T bits to the left.
001D
mpp
001E
shldc
multiply partial product (used for multiplication)
shift left and decrement conditionally (used for division)
Funit16 Instructions (cont.) (fcode = lower 6-bits of opcode)
Code
Name
Function
0020
TRUE
Set all bits in T to ‘1’.
0021
FALSE
0022
0023
NOT
0=
0<
0024
U>
T <= TRUE if N > T (unsigned), else T <= FALSE
0025
U<
T <= TRUE if N < T (unsigned), else T <= FALSE
0026
=
0027
U>=
T <= TRUE if N >= T (unsigned), else T <= FALSE
0028
U<=
T <= TRUE if N1 <= T (unsigned), else T <= FALSE
0029
<>
002A
>
T <= TRUE if N1 > T (signed), else T <= FALSE
002B
<
T <= TRUE if N1 < T (signed), else T <= FALSE
002C
>=
T <= TRUE if N1 >= T (signed), else T <= FALSE
002D
<=
T <= TRUE if N1 <= T (signed), else T <= FALSE
Clear all bits in T to ‘0’.
TRUE if all bits in T are ‘0’.
TRUE if sign bit of T is ‘1’.
T <= TRUE if N = T, else T <= FALSE
T <= TRUE if N /= T, else T <= FALSE
M
R
0
psel
The FC16
Forth Core
Pmux
P1
T
0
1
rinsel
Rmux 1
Rin
Pin
P(15:0)
pload
pinc
clr
clk
PC
plus1
P
rsel
rload
rdec
ReturnStack
clr
clk
rpush
rpop
E1(15:0)
S(1:8)
R
M(15:0)
M
y
M
irload
0
1
2
E1 E2
3
4
5
Tmux
clr
clk
IR
E2(15:0)
S
N2
6
N
7
tsel(2:0)
Tin
tload
icode
R
B(1:4)
T
clr
nload
nsel
ssel
clr
clk
dpush
dpop
DataStack
clk
oe
FC16_control
we
N2
cs
N
T
T(15:0)
digload
N(15:0)
LCD_RW
Funit16
LCD_RS
LCD_E
y1(15:0)
The FC16
Forth Core
Fcode(5:0)
y(15:0)
Return Stack
Rin(15:0)
ReturnStack
rsel
rsel
rload
rdec
clr
clk
rpush
rpop
1
Rmux
0
r_in
rload
rdec
clr
clk
R
R
clr
clk
rpush
Stack32x16
f ull
rpop
empty
R1
R(15:0)
Return Stack Instructions
Name
Function
>R
“To-R” Pop T and push it on return stack
R>
“R-from” Pop return stack R and push it into T
R@
“R-fetch” Copy R to T and push register stack
R>DROP
“R-from-drop” Pop return stack R and throw it
away
DRJNE
Decrement R and jump if R is not zero
CALL (:)
Call subroutine (colon)
RET (;)
Subroutine return (semi-colon)
M
R
0
psel
The FC16
Forth Core
Pmux
P1
T
0
1
rinsel
Rmux 1
Rin
Pin
P(15:0)
pload
pinc
clr
clk
PC
plus1
P
rsel
rload
rdec
ReturnStack
clr
clk
rpush
rpop
E1(15:0)
S(1:8)
R
M(15:0)
M
y
M
irload
0
1
2
E1 E2
3
4
5
Tmux
clr
clk
IR
E2(15:0)
S
N2
6
N
7
tsel(2:0)
Tin
tload
icode
R
B(1:4)
T
clr
nload
nsel
ssel
clr
clk
dpush
dpop
DataStack
clk
oe
FC16_control
we
N2
cs
N
T
T(15:0)
digload
N(15:0)
LCD_RW
Funit16
LCD_RS
LCD_E
y1(15:0)
The FC16
Forth Core
Fcode(5:0)
y(15:0)
bn
mclk
IBUFG
clkdiv
DIO2main
cclk
Top Level Design
led
clr
P
clk
clk
clr
P
T(5:0)
addr(5:0)
T
Program
ROM
M
M
FC16
oe
we
cs
LCD_RW
N
buff3
LCD_RS
LCD_E
E1
Data(7:0)
DIO2 and Transfer Instructions
Name
Function
#ClkCyc
DIO2@
Fetch the 8-bit byte from the DIO2 data
bus and load it into T.
Store the byte in N at the DIO2 address
in T. Pop both T and N
Write instruction in N to the DIO2
LCD.
Write data in N to the DIO2 LCD.
1
JMP
Jump to inline address
2
JZ
Jump if all bits in T are ‘0’ and pop T
2
DIO2!
LCDinst!
LCDdata!
3
8
8
\ Test of DIO2 buttons, LEDs, and 7-seg disp
: D2DIG! ( n -- )
DUP 8 RSHIFT
7 DIO2!
6 DIO2! ;
: D2LD!
( n -- )
DUP 8 RSHIFT
5 DIO2!
4 DIO2! ;
: get.BTN2( -- n )
1 DIO2@
8 LSHIFT
0 DIO2@
OR ;
cs
oe
we
addr(5:0)
data(7:0)
1
1
0
xxxx00
btns(7:0)
1
1
0
xxxx01
‘0’&btns(14:8)
1
1
0
xxxx1x
switchs
1
0
000100
leds(7:0)
1
0
000101
leds(15:8)
1
0
000110
sseg_reg(7:0)
1
0
000111
sseg_reg(15:8)
\ n nHI
\ display nHI
\ display nLO
\ n nHI
\ display nHI
\ display nLO
\ btns(15:8)
\ btns(7:0)
0
0
0
0
: waitBTN2 ( -- n)
BEGIN
get.BTN2 0=
UNTIL
BEGIN
get.BTN2
UNTIL
get.BTN2 ;
: but>num ( n1 – n2 )
15 FOR
DUP 1 =
IF
R>
15 SWAP 1 >R
ELSE
U2/
THEN
NEXT
NIP ;
0
0
0
0
0
0
0
1
\ wait to lift finger
\ wait to press button
\
get buttons
\ loop 15 times
\
\
\
\
value matches
get loop value
find index
break out of loop
\ Shift button value
\ remove extra 1 from N
0
0
0
0
\ Test of DIO2 buttons, LEDs, and 7-seg disp
: main( -- )
BEGIN
waitBTN2
DUP D2LD!
but>num
D2DIG!
AGAIN ;
\
\
\
\
wait to push BTN2
display on LEDs
find button number
display on 7-seg disp
Multiplication
UM*
( u1 u2 -- upL upH )
T
N
N2
mpp (multiply partial product)
if N(0) = 1 then
adsh
else
sh
end if;
: UM*
( u1 u2 - upL upH )
0
mpp mpp mpp mpp
mpp mpp mpp mpp
mpp mpp mpp mpp
mpp mpp mpp mpp
ROT_DROP ;
: *
( n1 n2 – n1*n2 )
UM* DROP ;
Division
shldc
sll T & N;
if T[16:8] > N2 then
T := T - (0 & N2);
N(0) := ‘1’;
end if;
Dividend
T
N2
Divisor
N
32 / 16 = 16:16 Unsigned Division
: UM/MOD ( unL unH un
-ROT
shldc shldc shldc
shldc shldc shldc
shldc shldc shldc
shldc shldc shldc
ROT_DROP_SWAP ;
-- ur uq )
shldc
shldc
shldc
shldc
32 / 16 = 32:16 Unsigned Division
: MU/MOD
( ud un -- urem udquot )
>R 0 R@
\ udL udH 0 un
UM/MOD
\ udL remH quotH
R>
\ udL remH quotH un
SWAP >R
\ udL remH un
UM/MOD
\ remL quotL
R> ;
\ remL quotL quotH
LCD Display
Connector A
2
GND
4
8
data
control
6
4
address
5VDC
regulator
JTAG
VU
Connector B
10
3
PS2
port
VGA
port
16x2
LCD
VDD
XC95108
PC84
4 7-seg.
displays
15 LEDs
8 switches
15 button
keypad
DIO2 and Transfer Instructions
Name
Function
#ClkCyc
DIO2@
Fetch the 8-bit byte from the DIO2 data
bus and load it into T.
Store the byte in N at the DIO2 address
in T. Pop both T and N
Write instruction in N to the DIO2
LCD.
Write data in N to the DIO2 LCD.
1
JMP
Jump to inline address
2
JZ
Jump if all bits in T are ‘0’ and pop T
2
DIO2!
LCDinst!
LCDdata!
3
8
8
LCD.WHP
HEX
: 1ms_Delay( -- )
30D1 FOR NEXT ;
: 30ms.Delay ( -- )
1E FOR 1ms_Delay NEXT ;
: lcd.init
( -- )
30ms.delay
3C 0 LCDinst!
1ms_Delay
0f 0 LCDinst!
1ms_Delay
1 0 LCDinst!
1ms_Delay 1ms_Delay
6 0 LCDinst!
1ms_Delay ;
\ 2 x 40 display
\ display on
\ display clear
\ entry mode
LCD.WHP (cont.)
: clear.lcd( -- )
1 0 LCDinst!
\ display clear
1ms_Delay 1ms_Delay ;
: crlf.lcd( -- )
C0 0 LCDinst!
\ set address 40
1ms_Delay 1ms_Delay ;
: hex2asc
( n -- asc )
F AND
DUP 9 >
IF
37 +
ELSE
30 +
THEN ;
\ mask upper nibble
\ if n > 9
\
add $37
\ else add $30
LCD.WHP (cont.)
: hex>lcd
( hex -- )
hex2asc 0 LCDdata!
1ms_Delay
;
: u.lcd
( u -- )
DUP C RSHIFT
hex>lcd
DUP 8 RSHIFT
hex>lcd
DUP 4 RSHIFT
hex>lcd
hex>lcd ;
A simple decimal calculator
HEX
: get.dec ( -- n k )
0
BEGIN
waitBTN2 but>num
DUP A <
WHILE
DUP hex>lcd
SWAP A * +
REPEAT ;
: display.dec( ud -- )
1 >R
BEGIN
A MU/MOD
OVER OVER XOR
WHILE
R> 1+ >R
REPEAT
DROP DROP
R>
FOR
hex>lcd
NEXT ;
\ k = non-dec key
\ decimal # n in hex
\ press button
\ while 0 - 9
\ display on lcd
\ convert to hex
\ save count
\ while dquot <> 0
\ inc count
\ drop 0 0
\ get count
\ display all digits
: main( -- )
lcd.init
A simple
BEGIN
BEGIN
get.dec
DUP E =
WHILE
clear.lcd DROP
REPEAT
DUP C =
IF
DROP
UM* \ multiply
clear.lcd display.dec
ELSE
DUP D =\ press D key to
IF
DROP
0 SWAP UM/MOD
clear.lcd 0 display.dec
crlf.lcd 0 display.dec
ELSE
B =
IF
DROP clear.lcd
THEN
THEN
THEN
AGAIN ;
decimal calculator (cont.)
\ enter decimal number
\ followed be E key
\ press C key to
\ display product
\ divide
\ display quotient
\ display remainder
\ press B key to
\ clear the display
Digilab IO2 Board
•16x2 character LCD
•Four seven segment displays
•16 LEDs in three colors
•8 switches
•15 pushbutton keypad
•8-bit VGA port
•PS/2 port
Summary
• A Forth core has been implemented on a
Xilinx Spartan II FPGA
• This Forth core allows rapid prototyping of
the Digilent DIO2 board
– Easy access to the LEDs, 7-segment displays,
LCD display, switches, and pushbuttons
• Demonstrated by implementing a simple
decimal calculator