diff --git a/demo/Makefile b/demo/Makefile index eac8a3b..ec591dc 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -23,7 +23,8 @@ ML_RTL = \ ../rtl/top.v \ ../rtl/sequencer.v \ ../rtl/compute.v \ - ../rtl/memory.v + ../rtl/memory.v \ + ../rtl/spi_client.v ##################################################################### diff --git a/demo/mlaccel.pcf b/demo/mlaccel.pcf index f33a776..a1b8236 100644 --- a/demo/mlaccel.pcf +++ b/demo/mlaccel.pcf @@ -1,12 +1,12 @@ set_io clock 35 -set_io qpi_csb 2 -set_io qpi_clk 4 +set_io spi_csb 2 +set_io spi_clk 46 -set_io qpi_io0 47 -set_io qpi_io1 45 -set_io qpi_io2 3 -set_io qpi_io3 48 +set_io spi_mosi 44 +set_io spi_miso 47 -set_io qpi_rdy 46 -set_io qpi_err 44 +set_io spi_rdy 45 +set_io spi_err 48 + +# diff --git a/pi/README.md b/pi/README.md new file mode 100644 index 0000000..ff3f9f5 --- /dev/null +++ b/pi/README.md @@ -0,0 +1,46 @@ +# Raspberry Pi Support + +## Run the mlaccel testbench with Python + +Enable spi with raspi-config: + +* spidev for spi comms + +Install Python modules spidev and RPi.GPIO: + +* sudo pip install spidev +* sudo pip install RPi.GPIO + +Connect the Pi's SPI pins to the pins defined in the [UP5k dev board's pcf](../demo/mlaccel.pcf). + +![pinout](pinout.jpeg) + +Run the test: + + python spi_test.py + +## Camera SPI Demo + +This demo will eventually stream video to the mlaccel core over SPI. For now it just +captures frames and sends the raw data over SPI to an imaginary receiver. + +Install opencv the easy way: + + sudo apt-get update + sudo apt-get install python-opencv + +Install Python modules picamera and spidev: + + sudo pip install "picamera[array]" + sudo pip install spidev + +Enable interfaces with raspi-config: + +* enable camera for camera module +* spidev for spi comms + +Now [cam_to_spi.py](cam_to_spi.py) should: + +* read a frame from the camera +* resize according to the resolution set by export_resolution +* send the frame row by row over SPI diff --git a/pi/cam_to_spi.py b/pi/cam_to_spi.py new file mode 100644 index 0000000..e56910b --- /dev/null +++ b/pi/cam_to_spi.py @@ -0,0 +1,57 @@ +# import the necessary packages +from picamera.array import PiRGBArray +from picamera import PiCamera +import spidev +import time +import cv2 + +# initialize the camera and grab a reference to the raw camera capture +camera = PiCamera() + +export_resolution = (16, 16) +camera_res = (32, 32) + +camera.resolution = camera_res +camera.framerate = 32 +rawCapture = PiRGBArray(camera, size=camera_res) + +# allow the camera to warmup +time.sleep(0.1) + + +import spidev +spi = spidev.SpiDev() +spi.open(0, 0) +spi.max_speed_hz = 8000000 + +# capture frames from the camera +time_start = time.time() +frames = 0 +for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): + # grab the raw NumPy array representing the image, then initialize the timestamp + # and occupied/unoccupied text + image = frame.array + + #grey scale + image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + + # resize + if export_resolution != camera_res: + image = cv2.resize(image, dsize=export_resolution, interpolation=cv2.INTER_CUBIC) + + #cv2.imshow("Frame", image) + key = cv2.waitKey(1) & 0xFF + + #print(image[0]) + for row in image: + spi.xfer(row.tolist()) + # clear the stream in preparation for the next frame + rawCapture.truncate(0) + + # if the `q` key was pressed, break from the loop + if key == ord("q"): + break + frames += 1 + if frames % 100 == 0: + print(time.time() - time_start) + time_start = time.time() diff --git a/pi/demo.hex b/pi/demo.hex new file mode 100644 index 0000000..de33a37 --- /dev/null +++ b/pi/demo.hex @@ -0,0 +1,2573 @@ +@00000 +0a 00 00 00 +08 00 00 00 +0c 00 00 00 +0e 00 00 00 +04 00 a6 00 +07 00 0e 00 +05 00 f8 00 +07 00 0c 00 +06 00 5c 01 +07 00 0c 00 +45 06 c0 01 +07 00 0c 00 +46 06 24 02 +07 00 0c 00 +85 0c 88 02 +07 00 0c 00 +86 0c ec 02 +07 00 0c 00 +c5 12 50 03 +07 00 0c 00 +c6 12 b4 03 +07 00 0c 00 +0a 00 e8 00 +08 00 18 04 +0c 00 00 80 +0e 00 00 00 +00 00 00 00 +01 00 5e 00 +05 00 e0 00 +45 00 e4 00 +08 00 00 80 +0c 00 40 8c +0e 00 00 00 +00 00 00 00 +2d 00 00 00 +69 00 04 00 +29 00 08 00 +11 00 00 00 +69 00 0c 00 +69 00 10 00 +15 80 00 00 +2b 00 14 00 +69 00 18 00 +11 00 01 00 +29 00 1c 00 +15 80 01 00 +02 00 00 00 +01 00 68 00 +01 00 68 00 +01 00 68 00 +01 00 68 00 +02 00 00 00 +01 00 80 00 +01 00 80 00 +01 00 80 00 +01 00 80 00 +01 00 80 00 +01 00 80 00 +01 00 80 00 +0b 00 04 00 +09 00 00 f2 +0d 00 c1 f3 +4f 06 00 00 +02 00 00 00 +01 00 8a 00 +01 00 8a 00 +01 00 8a 00 +01 00 8a 00 +02 00 00 00 +01 00 9c 00 +01 00 9c 00 +01 00 9c 00 +01 00 9c 00 +01 00 9c 00 +01 00 9c 00 +01 00 9c 00 +09 00 10 00 +02 00 00 00 +03 80 0e 00 +03 80 0e 00 +03 80 0e 00 +03 80 0e 00 +02 00 00 00 +1c 00 00 00 +28 00 00 00 +68 00 04 00 +a8 00 08 00 +e8 00 0c 00 +28 01 10 00 +68 01 80 00 +a8 01 84 00 +e8 01 88 00 +28 02 8c 00 +68 02 90 00 +09 00 04 00 +a8 02 fc 00 +e8 02 00 01 +28 03 04 01 +68 03 08 01 +a8 03 0c 01 +0d 00 04 00 +e8 03 7c 01 +28 04 80 01 +68 04 84 01 +a8 04 88 01 +e8 04 8c 01 +28 05 fc 01 +68 05 00 02 +a8 05 04 02 +e8 05 08 02 +28 06 0c 02 +94 02 fc ff +00 01 00 01 +00 01 00 01 +01 00 01 00 +01 00 01 00 +00 01 00 00 +02 03 00 00 +04 05 00 00 +06 07 00 00 +08 09 00 00 +0a 0b 00 00 +0c 0d 00 00 +0e 0f 00 00 +01 02 03 04 +05 06 07 08 +02 02 03 04 +05 06 07 08 +03 02 03 04 +05 06 07 08 +04 02 03 04 +05 06 07 08 +05 02 03 04 +05 06 07 08 +06 02 03 04 +05 06 07 08 +07 02 03 04 +05 06 07 08 +08 02 03 04 +05 06 07 08 +09 02 03 04 +05 06 07 08 +10 02 03 04 +05 06 07 08 +11 02 03 04 +05 06 07 08 +12 02 03 04 +05 06 07 08 +13 02 03 04 +05 06 07 08 +14 02 03 04 +05 06 07 08 +15 02 03 04 +05 06 07 08 +16 02 03 04 +05 06 07 08 +17 02 03 04 +05 06 07 08 +18 02 03 04 +05 06 07 08 +19 02 03 04 +05 06 07 08 +20 02 03 04 +05 06 07 08 +21 02 03 04 +05 06 07 08 +22 02 03 04 +05 06 07 08 +23 02 03 04 +05 06 07 08 +24 02 03 04 +05 06 07 08 +25 02 03 04 +05 06 07 08 +01 02 03 04 +05 06 07 18 +02 02 03 04 +05 06 07 18 +03 02 03 04 +05 06 07 18 +04 02 03 04 +05 06 07 18 +05 02 03 04 +05 06 07 18 +06 02 03 04 +05 06 07 18 +07 02 03 04 +05 06 07 18 +08 02 03 04 +05 06 07 18 +09 02 03 04 +05 06 07 18 +10 02 03 04 +05 06 07 18 +11 02 03 04 +05 06 07 18 +12 02 03 04 +05 06 07 18 +13 02 03 04 +05 06 07 18 +14 02 03 04 +05 06 07 18 +15 02 03 04 +05 06 07 18 +16 02 03 04 +05 06 07 18 +17 02 03 04 +05 06 07 18 +18 02 03 04 +05 06 07 18 +19 02 03 04 +05 06 07 18 +20 02 03 04 +05 06 07 18 +21 02 03 04 +05 06 07 18 +22 02 03 04 +05 06 07 18 +23 02 03 04 +05 06 07 18 +24 02 03 04 +05 06 07 18 +25 02 03 04 +05 06 07 18 +01 02 03 04 +05 06 27 08 +02 02 03 04 +05 06 27 08 +03 02 03 04 +05 06 27 08 +04 02 03 04 +05 06 27 08 +05 02 03 04 +05 06 27 08 +06 02 03 04 +05 06 27 08 +07 02 03 04 +05 06 27 08 +08 02 03 04 +05 06 27 08 +09 02 03 04 +05 06 27 08 +10 02 03 04 +05 06 27 08 +11 02 03 04 +05 06 27 08 +12 02 03 04 +05 06 27 08 +13 02 03 04 +05 06 27 08 +14 02 03 04 +05 06 27 08 +15 02 03 04 +05 06 27 08 +16 02 03 04 +05 06 27 08 +17 02 03 04 +05 06 27 08 +18 02 03 04 +05 06 27 08 +19 02 03 04 +05 06 27 08 +20 02 03 04 +05 06 27 08 +21 02 03 04 +05 06 27 08 +22 02 03 04 +05 06 27 08 +23 02 03 04 +05 06 27 08 +24 02 03 04 +05 06 27 08 +25 02 03 04 +05 06 27 08 +01 02 03 04 +05 36 07 08 +02 02 03 04 +05 36 07 08 +03 02 03 04 +05 36 07 08 +04 02 03 04 +05 36 07 08 +05 02 03 04 +05 36 07 08 +06 02 03 04 +05 36 07 08 +07 02 03 04 +05 36 07 08 +08 02 03 04 +05 36 07 08 +09 02 03 04 +05 36 07 08 +10 02 03 04 +05 36 07 08 +11 02 03 04 +05 36 07 08 +12 02 03 04 +05 36 07 08 +13 02 03 04 +05 36 07 08 +14 02 03 04 +05 36 07 08 +15 02 03 04 +05 36 07 08 +16 02 03 04 +05 36 07 08 +17 02 03 04 +05 36 07 08 +18 02 03 04 +05 36 07 08 +19 02 03 04 +05 36 07 08 +20 02 03 04 +05 36 07 08 +21 02 03 04 +05 36 07 08 +22 02 03 04 +05 36 07 08 +23 02 03 04 +05 36 07 08 +24 02 03 04 +05 36 07 08 +25 02 03 04 +05 36 07 08 +01 02 03 04 +45 06 07 08 +02 02 03 04 +45 06 07 08 +03 02 03 04 +45 06 07 08 +04 02 03 04 +45 06 07 08 +05 02 03 04 +45 06 07 08 +06 02 03 04 +45 06 07 08 +07 02 03 04 +45 06 07 08 +08 02 03 04 +45 06 07 08 +09 02 03 04 +45 06 07 08 +10 02 03 04 +45 06 07 08 +11 02 03 04 +45 06 07 08 +12 02 03 04 +45 06 07 08 +13 02 03 04 +45 06 07 08 +14 02 03 04 +45 06 07 08 +15 02 03 04 +45 06 07 08 +16 02 03 04 +45 06 07 08 +17 02 03 04 +45 06 07 08 +18 02 03 04 +45 06 07 08 +19 02 03 04 +45 06 07 08 +20 02 03 04 +45 06 07 08 +21 02 03 04 +45 06 07 08 +22 02 03 04 +45 06 07 08 +23 02 03 04 +45 06 07 08 +24 02 03 04 +45 06 07 08 +25 02 03 04 +45 06 07 08 +01 02 03 54 +05 06 07 08 +02 02 03 54 +05 06 07 08 +03 02 03 54 +05 06 07 08 +04 02 03 54 +05 06 07 08 +05 02 03 54 +05 06 07 08 +06 02 03 54 +05 06 07 08 +07 02 03 54 +05 06 07 08 +08 02 03 54 +05 06 07 08 +09 02 03 54 +05 06 07 08 +10 02 03 54 +05 06 07 08 +11 02 03 54 +05 06 07 08 +12 02 03 54 +05 06 07 08 +13 02 03 54 +05 06 07 08 +14 02 03 54 +05 06 07 08 +15 02 03 54 +05 06 07 08 +16 02 03 54 +05 06 07 08 +17 02 03 54 +05 06 07 08 +18 02 03 54 +05 06 07 08 +19 02 03 54 +05 06 07 08 +20 02 03 54 +05 06 07 08 +21 02 03 54 +05 06 07 08 +22 02 03 54 +05 06 07 08 +23 02 03 54 +05 06 07 08 +24 02 03 54 +05 06 07 08 +25 02 03 54 +05 06 07 08 +01 0e 32 5e +60 45 5b 1d +02 43 cf 5e +7a c9 66 9e +03 50 e9 02 +94 ad a1 f1 +04 fd a6 4f +98 35 b7 3e +05 3d 39 47 +3d ef e6 17 +06 de 9f 79 +be 6c 89 38 +07 1d 2d 1d +a0 a0 e8 42 +08 4c 68 51 +ec 03 f4 f5 +09 94 7e 9e +93 1c a4 c6 +10 a6 9e 8a +ff d4 25 7d +11 7f 60 4e +9d 7e be f6 +12 89 71 07 +50 e2 c0 1f +13 7f 69 07 +f2 d8 59 7b +14 1a 96 11 +14 d8 39 9a +15 71 f7 47 +41 24 13 17 +16 25 4f b4 +6d e4 04 06 +17 ea 3c 85 +ff e2 4a 51 +18 29 f5 da +61 39 49 4b +19 2c a5 b3 +ca 7b ef 0e +20 7e 6c 77 +06 e7 c6 59 +21 b1 13 3e +25 06 37 18 +22 fb 55 ec +20 c9 cb 16 +23 17 58 98 +df f1 cd af +24 29 65 b9 +cb e9 07 5e +25 ef d8 e7 +5f 20 b1 75 +01 46 7a ce +f7 a5 37 f6 +02 8c 70 d3 +4a 4b f9 46 +03 a7 36 d4 +d2 50 67 c2 +04 84 d3 11 +48 4b 67 cd +05 cc 02 af +c2 92 d3 d5 +06 4e 0d 74 +bf 75 df c8 +07 55 88 d9 +3d bd ef ed +08 56 b9 9a +88 d7 36 6d +09 58 23 99 +84 14 44 2a +10 b7 e7 00 +34 00 8b 8f +11 c4 a9 c4 +fc 17 ab fb +12 8f 58 53 +60 48 09 f2 +13 01 13 b1 +bd 2c 31 25 +14 64 ea 60 +a2 b7 f6 86 +15 63 17 01 +d9 e7 52 82 +16 d7 60 d4 +5d 47 6c de +17 57 03 ea +da ed 91 21 +18 6e 60 a6 +b9 44 71 08 +19 a4 3f 75 +e6 90 45 16 +20 a0 29 93 +b1 d6 07 59 +21 65 ff 33 +88 4e 51 25 +22 a3 25 e4 +62 f5 72 e4 +23 ae f4 b3 +bf 58 b6 5a +24 0e cb fc +23 51 c4 27 +25 a7 2d d4 +10 bb 8b 36 +ae ee eb c4 +88 2c 6e 61 +56 7f f9 71 +14 4b 8c 87 +c9 de 8e 8e +67 94 4a 81 +a0 51 72 7f +22 7b d9 37 +42 68 f8 9e +8c b9 5d 95 +c6 c1 a7 1a +f3 f3 ab f0 +12 4f 09 37 +f3 ea 42 7b +4f 05 9b 31 +00 19 e7 71 +30 f3 03 2e +96 7a 05 09 +e2 db d5 b0 +d3 bd 58 78 +d1 ac a7 0a +86 c4 68 c8 +8f 28 e9 22 +02 98 42 3c +4c 10 1f d1 +a9 6e 0a 6f +08 02 c1 8f +9a 3f f6 c4 +0a c7 0d 49 +75 d1 0d 1f +86 96 1a 8f +e1 b6 85 e0 +44 61 b0 5f +45 d5 ff be +f0 d6 cb 39 +69 95 44 56 +d8 b4 2f b7 +e7 6c 6f f9 +54 87 72 ad +5b 75 1a 4e +52 bc 4c 46 +f7 0d d3 fe +ab 38 2e 8d +2e bc 35 7e +ce 80 63 02 +b0 85 4d 66 +fe 71 af 51 +55 c0 02 70 +6f b8 47 45 +70 bd 1f f7 +7b 6c f5 03 +1b 5f 8f 34 +2a aa 6a d8 +4c f3 9f 48 +85 ec 47 32 +4f 55 4a 8e +54 f3 66 e0 +9d 1a 16 28 +77 a5 f4 d7 +5d b7 d9 e4 +31 3a 7e 33 +c1 60 ab 26 +22 48 47 4f +3d b3 92 a1 +a3 0d 6a b4 +73 2f 64 b2 +7e c3 ec 5e +a0 6a 1b 3e +08 d4 f4 b8 +65 28 75 27 +2f 0f 67 1c +0e cc 0f 3c +f8 d6 33 30 +7f 00 94 46 +7a ce f7 a5 +37 f6 da 33 +9d 01 f0 f9 +8d 1e 12 e8 +c8 0e 32 5e +60 45 5b 1d +47 fd 40 f8 +66 86 89 8c +70 d3 4a 4b +f9 46 92 67 +e0 c4 46 53 +f8 a8 ac 83 +bd 43 cf 5e +7a c9 66 9e +68 c4 fe 97 +f9 30 04 a7 +36 d4 d2 50 +67 c2 a8 21 +e2 a9 4b b1 +04 f3 78 65 +d1 50 e9 02 +94 ad a1 f1 +54 b6 af a5 +d9 64 61 84 +d3 11 48 4b +67 cd 6c 3b +b6 f4 d9 57 +47 c4 0f 2c +fa fd a6 4f +98 35 b7 3e +1c f1 25 f2 +ac df b1 cc +02 af c2 92 +d3 d5 e4 5f +ec 4c da a0 +f1 e5 fa 9d +8a 3d 39 47 +3d ef e6 17 +0d b3 7d 36 +7e 25 7a 4e +0d 74 bf 75 +df c8 14 89 +c6 36 52 b6 +c3 65 51 dd +8d de 9f 79 +be 6c 89 38 +ea 7c d9 36 +47 eb 82 55 +88 d9 3d bd +ef ed 5d e6 +48 1b eb 73 +45 9c c0 85 +c1 1d 2d 1d +a0 a0 e8 42 +2e 87 47 e5 +1b 5d 2f 56 +b9 9a 88 d7 +36 6d 2c 9c +59 8d 55 64 +74 00 c2 fb +71 4c 68 51 +ec 03 f4 f5 +40 2b e2 f8 +50 a8 da 58 +23 99 84 14 +44 2a 59 61 +76 e8 fe 86 +21 82 1d 9c +7e 94 7e 9e +93 1c a4 c6 +06 13 ac d9 +92 6b d3 b7 +e7 00 34 00 +8b 8f 4d 36 +a5 be 2a 0f +74 b2 a0 d1 +69 a6 9e 8a +ff d4 25 7d +d9 63 f4 ec +80 b9 99 c4 +a9 c4 fc 17 +ab fb e8 17 +1a 1e 4c c5 +f0 62 ea e3 +ae 7f 60 4e +9d 7e be f6 +13 c8 6a 0b +81 1c fb 8f +58 53 60 48 +09 f2 ef d3 +e9 3c ab eb +4c a2 96 d9 +60 89 71 07 +50 e2 c0 1f +b8 84 26 63 +d5 ca a0 01 +13 b1 bd 2c +31 25 72 28 +ce b9 4a 49 +0c a1 f4 ef +07 7f 69 07 +f2 d8 59 7b +21 bf d1 59 +27 c8 08 64 +ea 60 a2 b7 +f6 86 93 7c +a6 3a 7c 87 +5a 74 c8 b5 +ea 1a 96 11 +14 d8 39 9a +97 f4 76 5a +43 08 4d 63 +17 01 d9 e7 +52 82 14 1e +89 01 ae 00 +cf 71 5f 87 +bb 71 f7 47 +41 24 13 17 +cb cb 1c d5 +f8 d0 3f d7 +60 d4 5d 47 +6c de 9a 67 +5e b4 b8 3a +af da 00 94 +a3 25 4f b4 +6d e4 04 06 +e6 10 63 dd +0b 44 42 57 +03 ea da ed +91 21 3b 67 +3f 4b 8c d3 +83 7e 86 b0 +97 ea 3c 85 +ff e2 4a 51 +c8 52 68 59 +ba a8 93 6e +60 a6 b9 44 +71 08 2d 0f +fb 91 4f 41 +e4 5f ee 7f +a4 29 f5 da +61 39 49 4b +f8 1b ab 29 +75 73 5d a4 +3f 75 e6 90 +45 16 ae 36 +e7 62 ef dc +b6 a5 84 7a +ac 2c a5 b3 +ca 7b ef 0e +9b 38 7c 37 +50 77 e4 a0 +29 93 b1 d6 +07 59 d4 ca +ef 23 0a d2 +9d 81 99 cc +f3 7e 6c 77 +06 e7 c6 59 +5f ff 8e 5a +f7 23 d8 65 +ff 33 88 4e +51 25 35 c6 +bb 93 71 b8 +8d c2 8c 13 +05 b1 13 3e +25 06 37 18 +18 dc ff e3 +ca ec f6 a3 +25 e4 62 f5 +72 e4 d3 3a +c4 48 4d cc +93 1e 51 1a +85 fb 55 ec +20 c9 cb 16 +db d8 a1 b2 +67 36 ad ae +f4 b3 bf 58 +b6 5a 69 68 +8f 0e 52 f1 +ea 74 49 6a +3a 17 58 98 +df f1 cd af +42 75 7e 8e +08 21 55 0e +cb fc 23 51 +c4 27 05 ef +bb 08 f8 0d +de e1 7e e9 +71 29 65 b9 +cb e9 07 5e +5c 86 27 90 +15 3d 23 a7 +2d d4 10 bb +8b 36 81 9d +51 ac 24 8c +ba ec 4f 67 +42 ef d8 e7 +5f 20 b1 75 +30 26 f4 58 +c5 e9 79 8d +7d ac d5 34 +99 25 79 45 +b4 6c 82 be +72 3f 2c fb +c4 58 f3 d1 +08 8d e3 70 +58 78 98 61 +6d 42 6a e2 +22 b5 40 2a +04 0e 24 37 +2f 60 94 92 +c4 d5 58 0a +9a af 0d 57 +e9 48 37 d4 +b4 a5 2b a5 +f0 3b 57 a8 +73 f7 ec 6f +87 c4 d1 8e +aa 42 56 52 +ee d5 3d 39 +20 fd b0 24 +56 d3 b3 dc +45 1b be bc +60 c3 57 8d +b0 4f 4c 2f +6c 85 e8 a8 +53 e0 a6 95 +f0 43 34 56 +9b ff 03 0a +82 f1 2e 74 +9e 77 ac 89 +56 1f e4 38 +b7 c6 db 4d +37 12 5d 19 +a2 0e ac 2b +d0 b3 55 be +ce 01 42 81 +8b 9d d8 bc +7c 7b ad 7a +0c 9e 5e db +bd 19 2e f7 +2f 5f e9 8d +35 65 7c 10 +bd 42 0f 57 +3b a7 1c e3 +b9 0e cd be +e8 f3 ad b5 +cd 58 5f d5 +c8 79 6e 45 +7f da eb 99 +12 7a 9f a6 +54 1b 39 8f +a4 ad 7a 93 +7e c5 f7 a0 +fb 30 ae dd +25 a6 14 f6 +4b 77 9e 5d +c0 3d 68 af +11 be 8b 71 +50 ff 27 1a +6a 5a 04 05 +7c 30 95 3e +83 3d 4c 92 +c6 58 fe 68 +d2 a0 d4 10 +94 94 f4 82 +39 9e 98 f1 +a8 cf b6 82 +88 d7 6f 94 +5b 38 e6 00 +db 07 59 41 +6b de 35 76 +9d 8e d2 8b +e8 af c3 99 +71 42 24 ac +f7 1d 44 5a +57 c3 f0 e8 +e2 ef 80 e8 +de 2a 27 df +c3 c7 66 9c +00 af 75 50 +98 d3 cf 57 +24 09 8e 5e +ef 1a cb 4a +ee 3d 60 fc +d1 b8 e6 37 +32 fc f4 84 +55 1a d9 e4 +b4 30 d8 1c +57 cd 32 9f +59 b3 f4 e2 +d2 1d 43 1e +8d 96 e2 24 +4a b4 8b c6 +94 e8 d0 32 +18 25 f2 ca +96 36 4f 18 +b5 91 70 4c +d6 91 b6 d1 +86 5e 57 f9 +d7 49 5e b5 +01 ad db 13 +e5 d8 e4 b9 +0f d7 d7 9d +35 e3 3b 80 +a3 08 91 85 +d9 ff b7 d7 +f5 c9 96 d8 +f1 5a 33 9a +5f 37 11 29 +62 40 ea 54 +3e de fc 96 +80 25 a5 58 +f9 d9 dd dd +44 6c 90 30 +de 98 d1 aa +12 3c 37 f6 +db 7e 32 77 +87 1b 2e a0 +2b eb 13 33 +94 e3 27 ab +31 a3 7e 07 +6e 60 18 e1 +49 d0 65 4c +ee 60 89 6c +7c f2 53 cc +7f a8 9d 09 +54 af ee 2f +c0 92 25 07 +9a 40 f2 62 +7e 47 0f 17 +1c 18 21 ce +9f 4d a5 85 +9f 94 a5 c5 +81 06 7c 04 +27 97 55 22 +32 e7 9e 6c +23 c4 35 9e +69 05 6d c8 +0c ef 53 c4 +30 1b 95 05 +c7 e2 30 0b +e3 59 3b 48 +08 7f a6 29 +50 2a f8 6a +d2 05 85 ce +dc c3 ab 15 +b2 a8 56 19 +30 70 09 54 +c8 90 c2 b1 +8c 69 ba 53 +b8 15 c8 cc +d0 19 76 3d +87 ad ec 48 +f0 05 47 90 +3f 70 0d 0a +3c cf fb f3 +ca 58 0a c3 +49 57 ca 0a +7c 08 80 9f +f3 ea 2b 43 +18 b7 2f d5 +e6 c0 94 e0 +cd 00 c8 71 +b1 72 cc 34 +13 c2 32 8c +cd 0d 22 9c +ad a6 c6 cf +61 95 50 68 +41 18 72 42 +14 95 e3 5d +41 0f 87 9f +be ec d2 82 +2c ba cc e2 +51 0b be 57 +4b bd df 6d +50 f4 87 f2 +24 cb c0 8f +6a 8b fa 50 +ed 0d d6 28 +ad cb 25 01 +96 68 dd 21 +b5 15 4b b4 +b2 01 3b c7 +4e 1f 4f 7a +42 ce 7b 41 +4a 9a 19 53 +6e 25 f5 49 +f9 98 10 ab +e4 e1 44 d3 +ba 4c 1a b5 +b8 53 74 da +62 4c 3d af +1e 79 65 e6 +b1 ca cc 45 +65 48 5c 10 +50 55 41 8b +a2 94 b3 63 +fe 3a ce 26 +8c 92 68 aa +bc 98 02 cb +f3 b0 06 0c +a1 8a e9 81 +bd 35 46 d3 +52 23 e0 2c +5a b5 0b 1a +46 b9 d3 a6 +b5 93 71 82 +97 df 7e b0 +71 f0 72 5b +cf 72 fe 98 +8f 1a 5c fe +09 9e a2 0c +ee b0 16 bd +ab ad 63 87 +eb 60 61 9c +05 35 be d6 +38 14 0c 29 +18 28 89 f5 +fb 4b 1a f1 +8a c2 00 19 +85 e0 7b dd +90 b1 1c 3b +bb 2d 45 73 +9c 67 ce 3c +08 8d 52 48 +6b 69 93 94 +b0 68 e6 2b +f3 58 54 60 +66 56 67 9a +9b ba 80 7a +6c b7 2f c9 +76 10 58 7a +f1 f4 e1 a1 +ef 85 f2 ef +64 3f ab c0 +03 b4 b4 88 +25 3f fc 92 +d6 e0 da 7b +83 d8 4f ac +4d 6a 6b d1 +1a d0 b0 e6 +ea 72 35 17 +48 b4 f6 a2 +77 b9 76 2d +9d 0e b1 59 +45 79 7b 25 +67 2f ff cd +f5 49 ed ff +27 8c 4b 9f +0f 28 f1 e8 +b4 94 a6 1b +ec ca 1e 57 +6c fb e3 70 +78 81 9c 7f +89 5e be cc +68 88 ae 94 +be 2d 17 0a +a7 d5 f7 4d +87 c9 1f d4 +16 4a c0 24 +73 f6 81 0a +d2 b1 c0 6c +27 f8 f0 f1 +5f 70 17 db +f8 d9 9a 3c +53 30 77 81 +ba e1 3d bb +08 61 68 07 +46 91 e7 27 +45 e6 b3 f3 +02 c3 db 74 +98 2e 26 03 +06 c9 cb 8c +ca 6d 01 05 +ee 7e 57 ae +ae 71 75 26 +c4 d4 94 5f +7c 6c 46 7c +75 93 4e 28 +01 49 16 30 +b1 69 a0 69 +56 22 2e 46 +5a d7 7d 31 +d9 b3 c7 97 +20 d0 25 7a +a6 32 21 f8 +26 b7 c8 2b +ba ab 52 38 +4e 97 9c 95 +42 6c 6f 48 +69 b0 42 95 +65 62 b7 1c +d1 d7 6c 11 +18 3f c8 ee +fd c7 0f f3 +8e 2c 96 1e +78 32 44 d0 +07 6e af 0f +8b 9d 0b aa +d0 be 67 c3 +62 b5 fe 76 +80 ac 3f 29 +5f a6 05 e2 +3a f0 7c 98 +2a 92 19 c6 +1f 81 66 0e +32 6d ba e0 +26 2a 5a 62 +f7 6f 42 d7 +53 c2 a3 6a +a5 b2 bf 39 +57 2a 23 55 +fe ae 44 54 +82 82 47 7a +7f 6a 39 9a +63 77 6e 28 +e3 70 22 bb +f4 dd 41 12 +a2 54 04 30 +e5 a8 a7 15 +8b cf 12 0f +8f 24 89 bf +fa 4d 8f 6a +ef a8 dc d5 +84 04 70 11 +64 dc d9 0f +a7 2a 82 15 +f7 1f 19 3b +af f9 14 ab +91 d4 8e f0 +a1 90 43 6a +f9 a8 52 27 +f7 57 c3 ca +e3 18 2f c0 +59 59 5e 3e +f1 8a ab 93 +16 33 fe b1 +1d 3f 9d 0f +db f4 c0 75 +e8 88 d0 03 +0d ad a1 97 +ea c7 ed 3e +2a 95 1d 56 +b8 40 c4 f4 +69 c6 af 3c +3f fb 90 69 +f7 14 f5 50 +89 b1 ca 82 +c5 6a aa 22 +be 48 25 12 +6e ff 19 bc +c9 e7 3f f2 +30 08 22 a3 +d7 96 69 56 +1c 1e 19 2a +43 77 15 52 +13 75 72 3d +f1 bf d6 11 +ad 33 c4 b3 +e2 dc ff a1 +9e c2 f6 7e +5b 76 d6 e8 +8d 8a 51 a5 +bf f2 43 43 +e7 1b a8 c7 +e4 ba f2 f8 +82 e0 80 8b +d4 59 7c a2 +ee 18 f9 41 +b7 f8 cd fd +61 ab 60 1e +90 e8 52 71 +14 3f 1a 31 +80 73 bf 57 +01 75 12 10 +d0 08 42 d2 +9a af 44 c7 +30 22 70 9f +25 ba a4 36 +10 6c 35 d6 +b8 e6 ce e7 +97 d8 3a bc +71 a8 27 b0 +71 53 59 51 +4a 0b bd d9 +19 84 98 d2 +89 f1 c4 12 +4b 21 03 ac +85 74 7e 3a +82 8a 7c ce +2c 8a 78 74 +73 15 de 83 +98 fa 43 b6 +46 cb 6c 5c +94 02 7f eb +f4 5e b0 b6 +8d 62 0f b1 +af bf 34 dc +b7 08 38 a6 +d4 6d 7a cc +38 5f 03 32 +31 61 99 a0 +3d 79 eb 23 +0e b8 21 b4 +9c a1 e1 7d +8e f1 f7 d8 +10 22 66 ee +13 2a 81 10 +36 98 ca de +f9 a4 bb 8e +f6 8b c2 a1 +44 58 89 ce +19 97 84 09 +30 09 37 2c +29 42 75 ad +fb 18 c6 66 +14 78 5a 47 +d4 98 3e 98 +d7 84 8b d7 +f4 eb 23 cf +78 22 de 73 +cd 48 30 d6 +60 b8 67 c1 +9c a1 fe f5 +f1 31 16 76 +2e ef d5 4a +d2 3d 5c 05 +e5 cd af d4 +db 1b d0 af +48 35 93 1e +98 64 dd b7 +99 64 7f d4 +35 25 92 32 +24 a4 36 2e +58 1b 3d 73 +e4 0a a6 b9 +9d 20 7c 48 +f6 5b a0 a2 +b0 2e 2e ce +89 75 7a bc +e5 f2 db cd +cc 20 67 14 +bd 9a a8 68 +69 60 ec fb +08 04 2b 07 +e1 0f 1a 2a +cf b1 44 52 +11 4d 1e 3c +d7 13 0d ab +93 7d 61 17 +b0 11 1b 65 +c6 6b f5 45 +cd 71 17 24 +00 99 62 a9 +5f 03 33 e9 +9c a6 3c bb +9f 0f de 24 +52 9d 9f 6b +7d 18 d1 e5 +5e 54 5c b0 +5a d1 9c 58 +c3 37 cd e4 +17 85 43 bc +01 a6 90 ff +24 95 f2 ad +31 92 30 a8 +2b 8c 47 32 +32 30 9c 26 +eb 9c 12 d5 +c9 98 e2 46 +14 fd 08 47 +5d 2e 0d a9 +19 84 f9 6a +5e b9 f9 8f +bd 98 0b d7 +7e 31 c5 32 +97 ba ce 81 +46 d7 23 e0 +9e 5b fd 16 +a3 dc 35 38 +06 d3 34 08 +ec e8 b5 a0 +19 fd 21 11 +03 51 1c b6 +2f df 69 da +08 5b 52 bd +9f fe 21 45 +d5 bd 85 cb +66 15 7c 33 +d9 63 a2 69 +75 bd b5 0b +66 a8 80 93 +bc 18 72 23 +57 a2 35 2b +09 e7 b8 e9 +4c 57 27 6f +30 77 5f 14 +39 43 e1 48 +78 13 76 36 +7a 01 d4 c7 +c8 e2 9d 8b +29 7f 91 43 +06 d9 b6 3c +b7 84 a6 c5 +65 d5 56 d6 +d3 1f ea a2 +ce 22 46 39 +d0 5a 99 1d +4a 0a 05 86 +e6 85 88 ff +97 e0 b4 b2 +74 42 51 dc +fd 68 8a 70 +41 a3 7e 7b +1d fd 1a e2 +0e 73 3f 86 +63 35 2a 63 +30 b2 b9 45 +a4 6e 42 e6 +5d 78 d2 0e +36 6c 14 b2 +9a be 43 64 +8e 8a b5 d8 +7a 66 d3 50 +b5 3a 2a fa +0b 82 5a 16 +bd c1 55 80 +d8 da f5 a1 +53 e3 8b 19 +83 4a 4f ca +06 ca ed 9d +0d 10 6d 34 +32 82 9f ba +ea c7 63 0b +dc d7 d3 50 +bf 8a 99 6e +11 22 1f e0 +be 68 90 b5 +6e 45 77 bf +c5 0d cf 30 +99 5c 61 d6 +03 f1 ef 6b +81 a1 72 92 +32 03 f5 19 +1c 09 b8 e7 +be cf 99 57 +0b 42 6f 94 +41 ea 77 d5 +bc 6e db 33 +6d b1 fb 1c +1c c9 f9 8a +ca d5 e1 c2 +44 50 60 ea +d0 25 d6 7f +22 68 79 c2 +4a e2 e0 13 +53 ab 1e 65 +0c 43 1e 2c +53 2a 42 c9 +07 ec 63 3c +65 27 74 79 +42 de c9 9a +16 e8 8e f9 +01 49 81 b0 +19 21 07 ae +ca 68 ad e5 +99 f5 bf 80 +96 28 be bd +4b 01 6f ba +25 45 be 3d +85 50 f1 80 +b3 a9 d9 66 +b5 46 27 f1 +75 cb 1e 6d +10 25 bf 98 +86 8d 6f 02 +70 e5 9b b5 +ad 8c 36 53 +0e f8 cb 0e +cf 6e da d1 +76 e5 fe d8 +8e da a1 0e +61 4d d6 e1 +ed 42 dd 29 +cb 8f c7 4d +26 38 4c 6f +73 c2 59 3f +8b f0 ba 18 +81 2f 93 6a +3f fb f8 18 +c0 4e 9d 8a +e4 ab 6f 2c +0e db ab cc +25 2c b1 d7 +4a 74 c2 c6 +c8 6a 6a 9e +02 e8 cc 50 +44 c7 2a 5e +a1 a3 bd fa +7b aa 88 04 +92 1c 19 b7 +20 49 aa 77 +7e 12 c8 32 +1d 14 e7 b6 +e3 db 41 36 +8f 90 63 35 +85 d5 a1 10 +18 bd ca c2 +4b 15 60 6f +00 be 71 79 +ef 65 37 4d +7b 4f ba 9a +6f 4d 85 6b +e0 85 81 97 +df c3 50 e3 +87 c6 bd 90 +cb 7b 00 95 +69 4d d8 59 +39 4a f6 d1 +53 21 dd dd +64 93 92 10 +1c 94 56 cd +67 1b 10 ef +7f 37 d6 87 +6f b1 ff 5f +38 d7 57 e3 +c3 63 7f d2 +c3 00 5e 7e +be b2 5e 92 +93 f1 0d 43 +10 1d f7 ec +f8 07 18 f0 +b7 dd 84 40 +20 7d 39 89 +88 65 05 92 +05 9c 08 2c +fe a3 23 7c +35 e0 df d4 +22 e5 d4 fa +8a 02 29 e6 +00 a0 fd e3 +31 ae eb 56 +48 f8 fd 4c +1a 84 00 41 +1a 2b 61 99 +1d 42 23 46 +35 e8 7f 07 +d1 9c 2a 5b +7e 2f 31 6d +d4 03 89 c4 +6a bd 22 23 +05 21 46 ca +a5 e3 48 3e +db 64 1e 12 +ee d2 8e f6 +48 f8 70 92 +29 bf 98 b6 +0b b4 a9 9b +78 a5 ba 18 +9a e7 8b 79 +28 93 18 4a +3a b1 be 2d +5f 68 07 21 +67 8a 36 13 +9e 06 6e 5d +19 98 d7 9e +24 99 3a db +ad 82 13 46 +1d 22 1f b3 +45 f3 f3 49 +70 63 8c 1f +b0 30 52 a1 +1d c5 1c 3d +9b 9c 57 d2 +5e 75 ff 99 +86 7e c3 52 +22 01 d1 fe +00 48 c1 ae +d4 28 43 4c +8a 89 91 c6 +57 8a 0c 2b +d7 9c fa ac +ac 54 88 32 +3f d2 ac 01 +f6 a0 23 c3 +fa 4c ee 0e +b0 8a ac 2d +ef 74 c4 8a +2e b2 c4 36 +67 4a 11 9c +e5 b2 03 99 +16 ca 29 87 +6f 8d f9 0e +98 ac 80 04 +24 37 44 53 +54 10 77 5e +64 f3 2e e9 +06 bf 8b ab +23 eb ae 9a +4a 46 23 e7 +a2 bf 00 17 +fa 25 e4 98 +d1 7e 0c e0 +11 8f c9 22 +b8 de 74 ef +c9 93 9d e2 +3b 36 f3 21 +ae 73 ed a4 +4a 73 e0 44 +d4 54 d8 59 +67 d7 fa db +1d 20 18 b4 +61 c3 a8 c6 +eb f7 68 60 +70 d9 2f ba +77 ad 80 ac +dc 3a 6f 31 +06 13 ac d9 +92 6b d3 b7 +e7 00 34 00 +8b 8f 4d 36 +a5 be 2a 0f +74 b2 a0 d1 +69 a6 9e 8a +ff d4 25 7d +02 43 04 08 +ae e9 93 08 +81 d0 b8 41 +19 2e 00 43 +4b 8e 4a 6d +e3 e5 2b 93 +7c bc 1b f3 +45 94 b7 c0 +16 8b c6 e4 +f2 00 01 82 +ae c6 37 54 +44 a5 4b 39 +82 dc 42 b7 +5f be c0 c7 +d5 60 ac fe +51 28 49 f9 +e2 af db 48 +72 c0 05 6c +eb 5c 2d b5 +16 93 a2 17 +4d 0c 45 41 +47 d7 63 3b +5b 4a a3 79 +e2 81 a2 8f +ac 2c 34 18 +56 0a 00 62 +ae 2c 58 03 +6b 58 25 03 +8b 71 17 42 +1b 57 59 9e +51 b0 fb 73 +7e 64 b7 51 +0d e7 64 73 +f5 94 37 92 +4d 05 f2 fa +39 2a 3c 49 +e0 b3 8f aa +ed 3d a9 a3 +8c 5d a3 fd +34 a5 dc 4d +a8 f4 5e f7 +59 43 53 6b +a8 a2 b8 83 +1b 55 81 d0 +17 20 01 43 +1c 7c 9f a6 +e8 6b 31 47 +4a ee 3a 29 +49 3f 6c 08 +23 04 14 72 +25 20 6b fc +62 37 66 52 +b5 ad db 4f +93 f8 e7 0b +fe 24 ba f5 +af d1 5d f8 +06 c8 9d 06 +45 3a 18 f7 +71 91 aa dd +e9 45 b5 e5 +82 ce 14 95 +95 54 d8 fc +eb 42 1b 41 +c3 43 e5 85 +4a 64 58 0a +bf 2a 79 05 +ee 97 b6 9f +86 31 43 8b +c1 08 07 6b +0b f1 80 a0 +8e 3b d2 ed +40 7a 56 a9 +7d bd dd 4d +82 25 74 e7 +e5 bc b3 f2 +a5 59 df 40 +16 1e e9 19 +23 93 c0 d4 +a9 dd ea 6d +74 13 47 6b +46 fa 09 e5 +66 a3 41 ec +d3 9f a3 3b +f5 ff e9 ea +c6 e7 77 04 +b3 86 d1 26 +f9 95 7a d7 +22 a1 86 3d +76 7d 9b 15 +35 fa 7b 10 +08 08 d1 c7 +4c e1 45 4e +e0 80 66 5e +46 01 fb 51 +6c a5 04 b3 +f5 da 62 81 +d4 21 ec cd +d8 89 36 b5 +77 e0 04 1c +ff 43 a2 a1 +8f d6 0f d4 +de 11 16 96 +61 62 c9 b5 +c2 ba 18 08 +9a b9 ab f1 +26 ce a3 3c +94 11 09 20 +05 6e 74 7d +75 24 8b 77 +e0 51 ea 71 +09 51 0a 64 +59 75 13 33 +32 d0 51 a5 +83 6a 1e c4 +a1 a4 df e6 +10 91 fe 47 +8a 21 6b 7d +e8 04 15 b1 +2d 53 fe b6 +77 f9 e6 05 +87 1f ab 50 +da 8c 53 42 +b5 f6 3d 3c +b1 ae 6b 52 +94 69 4b 1a +a9 af 16 a4 +cb fa 3b 84 +b6 36 b2 32 +fe fb c9 49 +95 9a da 1f +bd e3 cb d8 +ba 8c 32 87 +7c 1a 3d e1 +21 bb d4 b5 +65 0b cf eb +f0 81 27 31 +73 3a 6c ce +b2 7c 6b 3e +9e bb 4a e5 +8b c3 35 fb +10 32 d7 68 +c2 a7 01 81 +c9 20 63 74 +a0 67 18 35 +e6 35 26 ec +d2 cd 4b 21 +fe ed 27 3f +18 1e e6 74 +43 c1 64 e1 +b1 e5 21 e6 +2c 51 55 13 +c4 26 4a 46 +7b fe d4 bb +9a 0c 79 e5 +41 e6 92 5c +1e 4a 7a da +31 ac bd f5 +4b 9d 2b 68 +70 73 6f f0 +13 15 17 d6 +a8 cd 6f 83 +72 9b d6 ae +c4 43 51 e1 +66 b5 29 c4 +45 e5 f1 94 +69 27 a2 2e +ea d6 d2 48 +7e 5c 2a 88 +94 e6 eb d8 +9d f4 ba f2 +8d e6 99 31 +ab b6 27 88 +6d eb e4 e0 +93 f6 02 47 +46 01 9b e6 +fa 07 49 54 +ea b7 29 e0 +d9 f5 ae e9 +32 64 58 1f +88 18 d2 28 +5d 69 31 7e +11 f4 ed 49 +d6 c0 c2 1a +95 89 4c eb +87 74 99 f4 +40 7b f1 c2 +98 1a 60 55 +fe 1e 4b ae +5c e9 d3 2d +b2 7f 9c c1 +1a ee ce 28 +70 6a 96 ec +e5 2a 81 4b +31 e0 f6 82 +7c 0a 1f cd +74 7e 88 2f +85 28 f4 4e +41 84 ba 42 +37 c8 91 d4 +a1 b1 93 70 +5d 00 a6 62 +fe 40 f7 67 +3d 57 ad af +7e b5 ce d3 +97 04 9a dd +48 4d 0b 06 +94 15 20 b2 +c3 57 7c df +cc 32 b8 7e +92 bd 70 e5 +9f b5 69 b4 +f2 ef 73 b7 +9b 42 1d 59 +a2 43 a7 16 +4f 6e 67 d3 +df ca 29 d4 +af de 1c fc +37 da 48 7e +fb 5b c5 6a +18 03 1e cd +5b d9 1a e1 +30 ec 50 59 +5b a5 64 96 +a3 1a 08 63 +4f b0 ec 9d +3b 1b 10 1a +f8 00 6f 5c +9e 58 e9 43 +5b 30 99 2c +73 e0 65 07 +d9 0c 22 fb +ea af 8f 34 +fb da 36 29 +50 ef 66 33 +a0 2a 7e 31 +30 16 d0 27 +2f d3 8a a8 +dd c5 79 17 +f1 d2 30 ea +24 9e 1c a1 +8f 28 c0 f0 +0b d3 df ed +76 15 f0 43 +06 c4 57 55 +91 c4 51 f6 +7f d2 cc 4b +aa 22 e9 14 +45 fe 3c 56 +d8 5f 65 63 +de 93 73 e7 +c7 f2 00 aa +a3 7d 00 81 +7e ee 9f e7 +0f de de 28 +c4 73 08 a3 +c4 f8 92 af +33 cf 69 3f +49 4d a7 e9 +67 11 9c 8b +22 5b 6b f5 +62 36 89 f3 +06 ff fd b4 +29 30 f6 d9 +4d e9 e8 a2 +19 c1 5e 7f +95 07 64 63 +57 07 f8 16 +2f cf 80 6e +76 71 23 ed +82 f3 67 1b +1f 0d bb b3 +90 e5 62 55 +9f 38 fd ae +39 55 03 39 +0e 30 80 05 +19 0b 57 b1 +be 8e 4e 3f +19 69 15 77 +47 12 83 ba +62 c6 b9 d1 +54 71 b5 87 +90 37 c5 f1 +a7 41 3f b6 +a0 34 58 68 +89 53 e3 75 +f8 d7 a4 e4 +2e d0 c5 be +88 bd 57 81 +c2 24 53 e5 +e7 8d 14 ab +ce b0 b3 84 +97 64 9f 6b +78 53 8b d4 +cf 19 83 30 +82 b3 2c 0f +6e e9 e4 c7 +57 d9 c0 29 +2d d0 10 0c +88 b3 2a f9 +ef 65 08 de +1c 16 20 e7 +53 28 4b 7a +20 cd 41 4d +1e b3 29 c7 +04 09 2a 4b +50 e4 2e 26 +3b b6 36 57 +5e 1a 84 b6 +3f ec ad 44 +b7 88 cf db +b5 fa 7b 28 +f1 15 45 b4 +32 09 91 bb +15 d1 71 39 +ee e0 1b 22 +bd ad 34 87 +1d 73 40 59 +8a 61 0c a7 +d1 29 14 03 +3e 63 9c f2 +fa bd b4 a5 +75 80 27 45 +65 0a a9 17 +6d 78 4a c7 +fb 4b 51 2a +40 41 e6 ce +8d fa 16 be +9a 12 de c1 +82 9e 44 e0 +cd 3e 5e 4a +5d 48 23 ee +51 d4 f9 86 +09 ab f6 66 +77 6c 06 59 +68 06 3b 91 +fe 97 76 3e +45 71 49 3b +e4 9e 02 45 +17 73 97 6c +54 22 64 93 +d4 da bd e6 +b9 70 ef ad +cb 12 7d fe +e7 70 c5 84 +53 82 56 a1 +1c 84 bd 53 +73 d6 2d d2 +4a eb e1 42 +b4 d6 11 df +04 5f 64 05 +b9 13 f4 ca +28 70 f6 99 +b9 bb b6 db +52 a2 2a 63 +ff 69 bc 24 +cd e5 de 75 +ae 8e c0 66 +c4 6d de 98 +51 08 87 1d +06 35 33 6d +78 5f fb 86 +24 f1 97 6e +4b c7 b0 38 +95 f6 6f e2 +6f ba 90 5d +53 2d 4f c6 +5d ab ae d5 +01 83 66 73 +c0 74 df 03 +eb 03 53 ab +6c aa 99 2a +69 5d f0 a1 +4d b3 cc ce +53 65 83 7c +da 4f d9 fd +33 2f 1a 67 +33 fc a6 0f +e7 64 3a 11 +53 93 6d e4 +99 c7 21 9e +e7 2f 22 12 +8b 70 62 23 +37 14 5e db +c3 91 13 24 +70 00 0e 89 +62 49 ab ca +41 94 ee ab +ed d2 12 d1 +2e c6 de 9b +d6 9a 6a 4b +96 ed 5c fd +7c 60 49 9f +44 0e f2 1e +c1 c3 12 f7 +db 19 c9 0e +9c 47 86 ee +30 e5 80 fa +f3 2f b6 27 +2b 09 0c 58 +a7 2b 07 16 +4a 3c 0a 5c +e9 a2 7f 01 +ec ce 13 c3 +8f e1 8b d7 +19 7c e0 30 +25 18 15 6b +92 31 41 1f +7a 24 d5 a4 +3e e4 84 60 +e9 91 c7 81 +8d 25 07 5c +96 7e 0b f4 +e4 e5 42 80 +80 55 07 6b +1b 42 73 40 +43 cf fa 59 +a3 98 15 7f +14 b4 b8 02 +9b 1a d3 1d +bd 82 df c5 +4e cb 39 19 +e0 00 46 1c +8a 51 11 ae +99 fb 13 14 +16 24 28 cf +6d fd 19 bf +21 95 78 76 +9d ed 1c a0 +c7 87 b0 a9 +a6 b1 af 38 +4d eb 49 21 +9c 31 82 9d +18 c7 98 73 +10 93 67 2b +a5 83 d4 b1 +40 56 e2 8f +55 41 4b 6b +21 35 f5 6a +85 80 b5 8d +3e dd 80 6d +20 a0 9c b9 +ad 65 cf 96 +9e 7a e8 ad +25 13 9d 01 +e1 7b a1 1e +f3 a8 3d bf +9c 0c 41 1b +df 40 08 d0 +50 2b 19 2f +16 ed 4e 99 +92 66 39 63 +7e b3 8c 9a +86 2e fa 3c +33 38 ac 74 +95 ef 8e 73 +d5 50 d5 7b +09 82 fa 6f +2c b9 89 95 +0a dc 13 e5 +1c 1c 45 b9 +9a 0b 07 77 +21 c0 d4 a3 +b4 40 14 16 +eb d4 4f 5e +8a fb 27 9b +a7 57 85 35 +62 f8 3f b3 +99 da 21 0b +19 28 c3 27 +12 db a2 21 +26 36 e6 42 +db 6e 5a df +11 e6 3f 89 +e6 ae 42 df +ae 08 e6 96 +d0 55 16 c4 +bd 2d 6e 30 +53 e5 fa 6e +ca 70 a2 e9 +14 ac 70 75 +f7 2d 5a 49 +37 63 8e 90 +f9 f9 55 46 +bf 94 e3 af +6f 11 b8 f2 +9d 99 eb fd +04 6b 39 33 +0a 5e 15 a0 +b4 80 6d 8c +a4 9e 4b 54 +19 ef e7 2e +72 4a 37 c6 +59 ac 85 54 +7c c9 39 aa +56 82 d8 59 +13 c4 b3 2e +2c 44 b6 80 +2e 2f a8 56 +fb 3f 4d ea +32 ad 94 34 +51 32 9f 99 +45 1d 44 37 +b8 47 d7 ac +33 f2 ff 79 +b6 ff 1d e9 +fd d1 d8 7f +0f 07 b2 72 +4e f8 6d c8 +3e d3 cf a4 +63 d3 d2 7e +7f bf 85 67 +9a 5e 0c d7 +53 cf 90 d7 +f6 cc 25 d7 +47 02 be e9 +e1 69 92 8f +91 94 cb 88 +d3 6c b0 78 +78 1d b3 e0 +c1 5a 64 49 +24 07 05 a7 +ee 92 c0 ea +e4 bb 94 1a +45 8b 05 ad +3f b4 25 f2 +cd e7 44 64 +b9 e7 4e 88 +33 1e f4 fe +b9 b9 a2 17 +5f 14 ba 1b +bc 93 79 1f +12 24 c8 e7 +50 fa 66 c6 +9c f3 0f a9 +1a 44 53 cf +1c 98 83 f1 +74 eb 55 18 +9a a7 ec fe +61 f6 ee 80 +e3 3d 13 48 +31 21 c8 c5 +e3 18 f9 ff +08 c6 a9 0a +8b e8 1b d7 +ba e8 94 fd +f1 37 06 7a +0f 33 1d e9 +7e d2 2e 4b +57 bd 70 92 +a2 8e 13 0c +b7 59 d7 95 +d2 5b 32 9f +ef 7f 5b 52 +a0 23 31 ce +83 d9 2e f3 +4c 3b 44 dd +ec dc 18 e1 +3a df 75 bd +9e 11 1d 5c +88 0c c7 68 +59 94 41 f0 +99 08 8c fb +72 8b 68 4b +8a 9d 7f c5 +11 52 b8 2d +6f 6b 40 22 +23 97 b0 db +01 18 4c 72 +28 29 fa 12 +94 4f 21 c0 +88 a5 dc a6 +dd fc 7d b8 +f4 68 9b 4b +df 31 fd 09 +57 02 b1 ea +40 5a f2 3a +2d cf 3a 87 +ee 8b 4f 20 +d5 f4 93 f0 +76 58 03 77 +a2 29 9c b6 +30 27 f6 20 +ed 4a ef 7e +46 f1 5a 40 +2a be 83 c5 +d7 44 64 38 +dc 74 68 7f +3e 90 97 94 +bd 2e f4 df +ab f0 26 e9 +aa da d2 51 +e3 dc a5 7c +68 1e 86 a3 +ad 42 3e d1 +60 95 e0 52 +e0 e3 ff 0a +6e 68 0c fa +31 c6 e0 df +76 63 6b d6 +3d 38 7f 4f +d8 e3 79 72 +13 12 1d a6 +0f b7 22 d6 +cc ef d0 90 +fd 87 0e a6 +49 74 bd ef +0a 8f 8d 08 +75 5b 9e 58 +ed 65 4b 89 +90 5f bd ee +13 c2 be 15 +99 ac 36 64 +db 6e be 7b +6c 5b 33 8e +27 2a db ff +2a 7e 72 70 +76 98 c3 f9 +31 bb ab 47 +89 36 89 34 +d2 c7 d7 d7 +40 1f 08 86 +4f 84 72 af +60 5b a0 64 +13 f1 71 74 +04 e7 e8 10 +90 9f db 25 +e3 ef 62 d5 +9a 5c 62 f2 +d0 7b d8 3d +0e 47 db 0e +55 b0 9b 2a +c0 b9 c2 94 +b0 28 b3 04 +4f 8d 57 22 +2b e3 23 58 +fe a1 90 71 +ac 7a 31 21 +64 68 e8 b7 +9b 62 2b d0 +b4 17 13 d0 +dc bc e4 90 +56 90 43 b5 +a9 e5 54 41 +52 ac da 00 +85 26 8c 94 +de a9 f5 ff +8e 5e fb 08 +30 ad d9 b0 +01 20 95 c5 +d7 14 58 de +6b 10 2c 15 +3a 2f 78 dd +0b 58 16 fe +14 8e 3d b3 +6d 9a 49 58 +54 6c 65 6d +94 69 0a d8 +10 53 ca 6a +b0 09 d1 67 +9b 99 be 3c +dc e9 00 b4 +5e b9 d8 eb +6c be 85 77 +f2 bc a4 99 +87 3f a5 55 +08 82 3b 25 +a1 bd d5 25 +ce 05 a2 b7 +1c fd 95 49 +ea 4c 22 07 +e0 a5 e4 79 +4d 0f 71 98 +4f 79 a6 46 +ba 22 79 a9 +a4 46 bf 7d +2c ff 12 26 +72 69 c2 dd +f6 0f 71 83 +3d 10 06 07 +06 7d b9 d8 +09 8a 81 f3 +5f 11 6a 0d +13 ee c0 9b +bb 30 85 35 +12 6f c9 f9 +2e 43 9c 24 +15 4b b9 5d +a3 2a 66 0f +fc 01 96 a5 +64 98 61 7f +c3 f3 75 85 +0f 23 77 54 +43 96 f9 e8 +b9 d2 4b 24 +1a 48 3a 39 +a8 44 ab c8 +1e 1c b0 df +02 a0 97 00 +96 93 14 84 +ac a7 05 bc +7f ee 14 1b +7c 24 5e c7 +f2 01 7b 9d +d2 e6 9a cf +08 0c 69 9c +6b b1 7f d8 +a0 13 11 d2 +ca 1a 38 75 +52 b3 81 d3 +8c 43 a6 cf +76 09 3b e1 +7a fb 92 a0 +e0 1c ba d4 +4f 4e 16 15 +42 56 02 7b +02 f6 f9 cc +f7 3f df 12 +e8 50 01 99 +c6 10 ee 87 +e6 77 9f 05 +e5 1b 94 42 +60 ee 7b 9d +d3 68 bc e1 +06 68 e0 89 +e5 b4 98 69 +67 4c d3 0f +70 75 62 fb +df 77 2f 0e +44 bc 30 0c +31 54 40 46 +af 52 36 ff +0a 41 f1 be +ad 34 aa 03 +e9 33 39 74 +8e 3c d5 62 +25 ef da f6 +a0 23 b9 75 +ab 51 b6 3a +2b 4c 73 63 +44 21 4c 97 +75 35 be 0c +4e 80 6d 73 +fb 43 e4 ea +72 2f 42 a1 +90 6f 3c be +f1 1d f1 d4 +1c eb de 46 +2d 97 36 72 +9b 6e 85 1e +66 cb 34 34 +5e 69 1f 6b +bd 31 b6 6a +e8 66 bb e1 +56 8b 37 46 +d0 13 db 6a +ce 1d e0 01 +d3 77 b0 62 +26 5e 7d ba +4f 37 52 c8 +01 11 0e 09 +fc 3b e1 ac +52 17 3c 2c +1e ad d2 98 +1e f7 ac 1f +23 1a 7a 05 +ed 6e 96 58 +47 4f 39 a0 +13 39 ed be +60 08 67 28 +a4 93 fb fc +08 a0 8c a0 +e3 57 ee 4a +cd 9f e4 9b +3d 11 c6 34 +d7 41 77 bf +1d 76 30 b8 +d0 68 a5 53 +57 69 2e 4e +1d b0 65 f8 +e3 6b 65 b6 +78 89 65 01 +e1 b8 82 55 +01 53 23 09 +92 b6 5f b2 +e4 48 d3 a8 +99 24 a5 2d +00 e1 2d 23 +d0 df b1 7c +12 d8 58 ab +f5 cc d3 5a +80 9f 71 d8 +0b 16 77 e5 +08 ca 29 6d +1a 8c 3e 69 +f9 c2 24 c4 +58 52 05 91 +da 67 4d 46 +22 47 e4 27 +9c 78 0f 24 +5c 14 30 54 +24 15 e0 1b +88 c1 28 3e +b5 4f a6 91 +7b 72 04 aa +68 40 bc ea +15 56 47 38 +b4 59 b3 e5 +6b 2b 3e b2 +e0 e6 e2 f4 +dc 8e cf b0 +d6 b5 d2 84 +db cb ae 72 +ea 81 e5 4a +0f ac cb 93 +3e ff 7c fd +31 8b c7 d0 +1f 96 55 0b +b4 1c ac 76 +27 30 d9 cf +f5 72 71 58 +82 8e 39 81 +dd b5 5d 19 +1b a9 c0 82 +80 e1 61 5e +70 a0 ff 24 +7d 2c b4 c5 +72 06 ea 49 +01 0b 15 c7 +7d aa 49 4f +1b 21 2a 16 +06 7d 46 d4 +55 3b 49 56 +f6 39 84 df +08 a1 0a 73 +e6 f9 66 c8 +5d ad 08 0d +b0 8a 70 12 +a7 e0 73 63 +be 89 94 85 +6e 24 ed 75 +67 7b c1 51 +9d 8b 0d 42 +7d 70 65 00 +aa 2e 86 9b +8f bf 04 df +3a 90 ed 63 +d0 8a f5 b1 +24 c3 31 5d +60 6b 7d 08 +91 b4 db 74 +ed b2 1c 24 +1c 30 2f 29 +8b f6 ca 4a +61 58 de ca +6b 58 c1 5c +95 0a b5 f2 +d6 2a 64 93 +f7 2e 46 a0 +b0 a7 11 a4 +b4 93 9b 64 +98 49 a1 37 +f3 7d cf 55 +4c c3 e3 02 +d8 a3 4e aa +84 a7 10 70 +c1 34 a3 7b +e1 6d 4b 90 +28 7e 7a 69 +f7 7b 8b c6 +22 2f 66 9d +39 e3 2e 8f +90 4e 36 dc +95 84 8c 9a +05 e7 c5 82 +14 4b ab 65 +3d c0 fb 0c +8c d8 08 e2 +08 c0 20 e0 +fc a4 47 4b +0a 66 bd 38 +9c 02 64 1d +b7 b7 4c 5b +30 8b 12 0e +3b 25 24 3c +1a 28 b3 d6 +d2 db d6 88 +9d 59 b9 e1 +8a 01 3f 4a +4b ed 85 eb +53 ba 70 51 +aa 19 f7 e9 +18 d1 ab 82 +1a ab d4 78 +75 54 ec 65 +40 83 f1 8c +f8 8e 33 e4 +b7 3e 51 11 +29 2b e7 31 +d6 f3 30 1e +66 59 f8 5a +1d 35 7c ec +80 8c 4a ce +55 24 14 0f +53 6a a5 9c +69 73 6d ef +00 20 ff 75 +99 8b 48 0b +18 af 4e 87 +b0 14 50 40 +a8 d9 28 e4 +c7 c9 8a c3 +01 76 50 39 +f4 e4 7e a8 +0d df a9 86 +2a 84 08 a6 +46 5b 72 f0 +c8 ed fa fd +43 f5 67 d3 +5e 7c 7c b3 +db 84 d9 aa +48 f7 71 35 +ca bf 25 07 +34 80 11 82 +5a a1 36 38 +2f 9b 60 25 +19 cb e7 e8 +62 63 0d d5 +9a 73 7b ea +1a 5c b0 bc +a4 54 ad 49 +30 45 9e 46 +29 1c 63 a3 +28 7d 0d ee +c5 45 ba f4 +86 4e 23 28 +13 ed 2e f1 +00 48 3d 6d +3e 39 b7 f0 +93 1b ea f6 +fc 7a 66 95 +4a 8a b1 e3 +83 f7 41 0d +77 eb c6 4c +d2 4f a8 25 +30 06 0e bf +4e ba 1d 97 +0a c8 8b 00 +e5 e3 8e 72 +11 09 c7 1b +3b f0 49 52 +43 7b 99 2e +54 7c 8c 93 +10 15 9b af +26 2b 43 a9 +2d 95 db 59 +da e1 f7 2c +64 51 27 30 +16 61 e0 a3 +ce 4e 38 b2 +95 a9 7c 58 +ca 91 26 58 +e4 ea cd 29 +67 ad a2 5a +9e 04 4d 36 +fb c6 8e 88 +b5 cd 26 2b +e1 4e 37 4b +2c d9 aa 85 +5a 70 ba c7 +b8 26 60 12 +ca 73 c5 8b +9c 5f d3 b2 +06 94 18 09 +c2 3e ac fa +0b 74 40 85 +f4 c4 c5 17 +42 6d 91 6a +49 d8 ab a4 +7c 54 ac ec +55 6a 08 58 +05 05 5a 90 +43 66 31 07 +69 ab 51 3e +e5 73 fe 94 +a3 98 8a b6 +d5 33 3b 32 +dc a6 7a c1 +91 c9 f1 0d +98 95 9a 32 +4a 0a 47 30 +ae ea bd 14 +6c e9 30 e3 +6a df ba 97 +af f2 c9 b9 +17 39 cb 61 +0a 71 81 66 +10 15 97 41 +7f cc 4d 87 +7a 9f b4 37 +8e b8 44 96 +eb cc 6d 4c +0e 3d 89 dc +d9 51 17 9b +37 a6 b5 4c +e9 b4 bb 2f +26 a4 e8 ef +44 8b ae 0c +67 b0 74 b2 +b1 72 31 5c +64 dd 86 75 +96 ba 10 3a +cc 50 d2 ce +99 b1 f2 e2 +7f 2f 60 b1 +86 6e 14 84 +27 dd 6f f2 +60 8e 44 2f +92 7d 9e 51 +39 1b f8 c1 +cc 15 0b 8e +72 6d a5 55 +f9 46 3d 0d +5b fc 5c 7f +a1 35 aa 0b +71 6a ae d6 +9a f3 3c a0 +b6 6c 9c f1 +ed 0e 5f c6 +ee ef 52 47 +57 33 bc d1 +9c 4a 08 02 +cc 99 f7 40 +73 c0 9d f5 +f8 5d 53 5f +9f 40 a7 3b +a4 6a f3 07 +ef 48 02 30 +c9 87 a7 01 +5d 06 c2 16 +58 19 a9 66 +70 04 af a7 +11 8c 23 78 +00 d5 b6 a5 +36 71 00 85 +1b 05 80 c2 +87 db e7 c9 +ce 92 5b 07 +a6 ba 4d 54 diff --git a/pi/demo_out.hex b/pi/demo_out.hex new file mode 100644 index 0000000..5340e6e --- /dev/null +++ b/pi/demo_out.hex @@ -0,0 +1,394 @@ +@10000 +14 15 26 25 33 0c 00 00 11 13 13 1f 27 18 6c 44 +13 16 1b 12 15 00 64 00 16 21 15 21 10 00 7f 09 +0d 12 09 17 00 00 00 42 14 1e 15 1c 00 08 00 00 +0a 10 0d 0a 00 11 00 00 05 0f 0d 00 05 18 00 16 +06 0a 13 02 02 1f 00 00 09 11 15 06 13 0e 74 49 +01 07 09 00 13 00 18 00 00 01 00 01 00 00 00 3f +00 00 00 15 00 00 00 28 00 00 00 06 00 00 24 2d +00 00 00 00 00 00 00 00 00 00 00 00 00 1a 59 00 +03 00 00 00 11 36 00 00 06 0a 01 00 25 36 05 11 +00 03 00 00 07 07 13 36 02 0e 00 00 0f 1d 37 29 +00 0b 0a 00 17 14 00 00 00 0d 09 00 22 0d 0a 00 +00 04 00 00 09 00 00 00 00 00 00 00 0c 04 22 00 +00 00 00 00 17 02 00 00 00 00 00 00 09 00 00 06 +00 00 00 08 00 00 2a 2a 00 00 00 00 00 18 7f 27 +0a 09 1d 15 42 00 00 0a 0b 0c 15 14 33 08 0b 00 +0d 0d 19 0d 20 00 29 58 12 19 13 19 26 00 27 45 +0a 0f 06 17 07 00 00 31 0a 0f 0b 15 00 01 00 14 +00 01 00 00 00 02 59 0b 00 01 00 00 0b 00 68 00 +00 00 00 00 07 08 47 27 00 00 00 00 19 01 1e 43 +00 02 00 00 21 00 28 1b 00 01 00 02 05 00 1d 00 +00 00 00 10 00 00 00 2e 00 00 00 0a 00 00 4e 00 +00 00 00 00 00 01 1d 00 00 00 00 00 00 2d 00 51 +00 00 00 00 00 2c 40 1e 00 00 00 00 10 40 7a 00 +00 00 00 00 0a 14 00 00 00 00 00 00 09 11 14 00 +00 00 00 00 11 00 00 1c 00 00 00 00 0d 05 27 00 +00 00 00 00 00 00 00 1b 00 00 00 00 00 00 00 14 +00 00 00 00 00 00 7f 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 27 00 00 00 00 00 00 00 00 00 +01 00 0e 01 2a 00 00 00 00 00 08 00 18 00 41 00 +07 07 1b 01 15 00 21 13 0c 13 19 0f 25 00 1a 28 +09 0f 13 0b 0c 00 00 2b 0a 11 18 0b 00 00 44 25 +0d 12 10 0c 05 05 00 7f 00 06 00 00 00 00 00 02 +00 00 03 00 00 00 00 00 00 00 00 00 03 00 00 00 +01 04 05 00 18 00 08 00 00 01 02 00 00 00 00 00 +00 00 07 13 00 00 00 7f 04 00 00 17 00 07 1b 2a +00 00 00 0a 00 12 00 7f 00 00 00 00 00 3a 00 00 +00 00 00 00 00 39 00 13 00 00 00 00 00 4a 21 00 +00 00 00 00 00 1e 00 07 00 00 00 00 05 1f 0f 00 +00 00 00 00 0b 08 00 23 00 00 00 00 0f 0a 5f 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 00 +00 00 00 00 00 00 00 63 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2c +00 00 0a 00 13 00 00 3e 00 00 0a 00 00 00 16 32 +0a 0b 20 10 04 00 7f 08 0b 14 20 18 1f 00 14 08 +0c 14 24 12 12 00 00 00 13 1b 2c 1e 0c 15 44 00 +12 19 24 26 1e 16 36 00 04 0c 0f 0a 0c 00 00 0c +02 07 1a 05 07 01 00 00 00 00 10 00 12 00 00 73 +00 00 0e 00 0f 00 71 20 00 01 0b 00 03 00 00 00 +00 00 17 00 01 00 7b 29 00 00 03 00 00 00 00 00 +00 00 06 00 00 00 00 00 00 00 00 00 00 1f 03 00 +00 00 00 00 00 09 05 00 00 00 00 00 00 1a 45 00 +00 00 00 00 00 00 00 70 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 +00 00 05 00 00 00 00 46 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 2f 00 00 09 00 00 04 00 00 +00 00 00 00 00 00 00 1e 00 00 00 00 06 00 00 7c +05 00 0b 00 0e 02 07 00 04 00 0d 00 0d 00 00 09 +0c 0b 1f 00 15 00 00 6d 0e 15 1c 0b 2e 00 25 41 +0c 0e 21 09 28 0a 00 00 13 18 2b 18 12 1e 00 06 +0f 14 21 1d 11 1b 00 6a 04 06 07 0b 00 00 7e 5e +00 00 10 00 00 00 19 00 00 00 03 00 00 00 00 33 +00 00 09 00 00 00 0c 12 02 03 0b 00 07 00 1d 00 +06 02 1f 00 01 00 59 20 00 00 08 00 00 00 00 1b +00 00 13 00 00 00 00 2c 00 00 00 00 00 1c 5e 00 +00 00 00 00 00 09 6a 3c 00 00 00 00 00 1d 4d 0f +02 02 0f 00 04 0d 00 00 00 00 03 00 00 00 40 00 +00 00 06 00 13 00 55 1b 00 00 03 00 06 07 00 23 +00 01 10 00 00 00 00 00 00 00 06 00 00 01 47 00 +00 00 03 00 00 08 37 28 00 00 10 00 00 19 4d 00 +00 00 00 00 00 07 00 00 00 00 00 00 07 00 00 00 +05 00 02 00 1b 1e 00 52 0f 07 17 00 27 24 52 51 +11 10 22 0b 2f 3c 4e 22 16 1a 2c 17 3d 47 00 00 +15 19 2c 14 34 42 00 00 12 15 2c 1b 19 38 22 1f +03 05 0c 1c 00 1f 09 00 00 00 00 0f 00 00 00 65 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f +00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 +00 00 0c 00 00 00 00 7c 00 00 00 00 00 00 00 32 +00 00 07 00 00 00 00 00 00 00 00 00 00 00 67 0b +00 00 00 00 00 00 00 7f 00 00 00 00 00 09 00 00 +01 06 04 00 00 1a 34 29 00 00 00 00 00 00 00 7f +00 00 00 00 12 00 50 30 00 00 00 00 07 06 00 00 +00 00 03 00 02 03 0d 00 00 00 06 00 02 10 19 05 +00 00 05 00 09 1b 00 30 00 00 0e 00 00 19 00 16 +00 00 04 00 00 0e 01 32 00 00 00 00 04 00 53 00 +00 00 00 00 00 2b 76 00 03 02 0c 00 07 22 16 3a +06 0a 13 00 16 37 00 00 0d 13 21 0f 1a 3a 64 00 +06 06 1b 00 1c 20 13 00 0d 0f 23 06 19 1d 00 00 +04 06 0b 16 06 13 54 39 04 06 0a 14 00 00 00 1c +00 00 04 00 00 00 00 12 00 02 07 00 00 00 00 02 +00 00 0b 00 00 00 00 00 00 00 11 00 00 00 00 7f +00 00 16 00 00 00 00 00 00 00 0c 00 00 00 30 00 +00 00 11 05 00 00 7b 00 00 00 00 00 00 00 2e 5a +00 00 00 00 00 00 13 00 00 00 00 00 00 00 23 00 +00 03 00 00 00 02 19 00 00 00 00 00 00 00 00 00 +00 00 00 00 10 00 01 00 00 00 00 00 14 07 00 0c +00 00 00 00 12 00 00 00 00 00 0d 00 1c 16 00 21 +00 00 0d 00 27 27 67 6f 00 00 11 00 1b 29 30 2a +00 00 0d 00 0b 20 20 00 00 00 04 00 0e 0a 00 53 +00 00 00 03 00 1a 1c 00 00 00 05 00 00 0e 05 44 +00 04 09 00 00 31 1b 1a 04 07 0e 07 00 28 45 23 +00 00 0b 00 00 19 00 59 05 05 13 00 00 18 52 1b +00 02 02 0d 00 0f 00 00 03 07 0f 1d 00 00 08 20 +00 00 07 07 00 00 11 2a 00 00 01 00 00 00 00 56 +00 00 06 00 00 00 02 24 00 03 0a 00 00 00 1a 7f +00 00 0b 00 00 00 32 6b 00 00 05 00 00 00 00 00 +01 00 15 00 06 00 00 07 00 00 00 00 01 00 00 00 +00 00 0c 00 01 00 09 68 00 05 04 00 15 00 00 0a +06 0e 0c 00 0d 00 40 3c 00 05 00 00 00 00 00 00 +07 0d 0f 00 11 00 00 00 03 08 07 00 0c 06 00 42 +00 00 09 00 01 00 00 00 06 07 1a 05 17 0e 0a 00 +04 03 1f 03 25 1d 00 00 00 00 18 00 21 0e 26 5c +00 00 17 00 16 09 00 22 00 00 17 00 15 01 63 59 +0b 0a 0a 17 0f 37 3d 00 05 06 11 05 19 19 67 00 +00 01 08 00 07 1a 00 6e 00 00 02 00 00 17 00 00 +00 00 00 00 00 0b 70 08 00 00 00 00 00 03 6d 00 +00 00 00 03 00 16 0c 57 05 09 04 1e 00 18 74 0a +04 0a 06 1a 00 13 00 03 0a 0f 0b 24 00 03 09 3d +02 07 0c 0b 00 06 2e 1b 0b 0c 13 17 00 04 31 00 +02 00 0d 00 00 00 00 00 00 00 00 00 00 00 0d 3b +00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 6d +00 00 00 00 04 00 2b 00 00 00 00 00 11 00 58 00 +00 02 00 00 11 00 08 00 00 00 00 00 00 00 00 00 +00 02 06 00 0a 0a 00 3d 00 00 00 00 09 08 02 00 +00 00 06 00 06 03 00 00 04 00 13 07 0e 13 00 00 +07 00 1d 05 1b 1e 00 10 02 01 1b 06 23 00 7a 00 +01 00 21 01 0f 05 66 00 09 0b 25 0a 12 00 00 7f +0a 09 0c 1e 17 20 50 4b 01 03 12 0b 14 00 09 5e +00 00 06 03 00 00 00 00 00 00 00 01 00 00 00 00 +00 00 00 00 00 05 00 21 00 00 00 00 00 0a 48 66 +00 00 00 08 00 22 3c 00 00 00 00 15 00 12 3d 1f +00 00 00 10 00 03 00 00 00 00 00 14 00 00 31 00 +00 03 09 06 00 0c 38 00 00 05 0c 12 00 06 53 38 +00 00 04 00 00 0c 00 00 00 00 00 00 00 00 00 7f +00 00 00 00 00 00 00 0d 00 00 00 00 00 00 05 00 +00 00 00 00 00 00 2f 76 00 00 00 00 0e 00 00 00 +00 00 00 00 0f 00 00 00 00 00 00 00 00 00 30 00 +00 00 00 00 00 0f 00 16 00 00 07 00 00 0a 00 04 +00 00 08 01 00 0b 00 04 0a 0b 17 22 08 10 6a 00 +0a 09 1f 1d 14 0f 00 63 05 0a 1c 21 1c 00 00 35 +07 08 1e 20 15 00 47 00 0c 0e 1d 1c 1d 00 00 44 +0c 0b 17 23 1a 16 50 00 03 04 15 0c 11 00 00 5f +00 00 03 00 00 00 00 00 00 00 00 00 00 00 42 21 +00 00 00 00 00 00 6d 00 00 00 00 00 00 00 00 2c +00 00 00 00 00 11 00 00 00 00 00 03 05 20 00 00 +02 02 09 0b 19 1b 00 00 02 06 0d 16 14 14 7f 79 +08 0e 20 11 19 30 00 00 07 0d 1e 16 09 11 00 77 +00 00 0b 00 00 10 00 1d 00 00 00 00 00 00 45 0f +00 00 00 00 01 00 05 00 00 00 00 00 00 00 00 00 +00 00 00 00 09 00 00 00 00 03 00 00 1a 00 00 1a +00 01 00 00 17 00 10 08 00 00 00 00 00 02 00 42 +01 00 09 00 00 17 78 00 00 00 0c 00 00 08 00 54 +00 00 02 00 00 00 00 12 00 00 02 11 04 05 25 00 +01 03 0f 13 11 00 00 00 00 00 0e 0c 20 00 00 5f +00 00 0a 18 1d 00 00 0d 03 07 11 0e 26 00 29 00 +05 04 0c 07 1a 00 37 63 03 03 11 00 23 00 18 7f +00 00 02 00 00 00 00 22 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 7f 00 00 00 00 00 00 00 00 +00 00 00 00 00 11 00 00 00 00 01 0d 08 1c 00 00 +00 00 02 15 1d 1c 7c 07 00 02 03 15 2f 1d 00 50 +02 06 0b 0e 48 39 00 00 08 0d 12 15 39 1f 2a 00 +00 00 03 00 12 22 00 00 00 00 00 00 01 04 2c 7f +00 00 00 00 07 00 00 00 00 00 00 00 00 00 00 2c +00 00 00 00 00 00 01 00 00 00 00 00 09 00 74 4b +00 02 00 00 17 01 00 00 03 05 08 00 00 22 00 00 +03 00 07 00 00 2f 00 00 00 00 0f 00 00 1a 04 53 +00 00 06 00 05 09 00 00 00 00 00 02 07 03 00 00 +00 00 04 01 0f 00 23 29 00 00 05 00 26 00 13 00 +00 00 08 0f 2e 00 00 0f 04 08 0e 00 30 00 00 00 +00 00 08 00 32 0c 00 24 06 03 16 07 3d 08 5c 00 +00 00 02 03 06 00 00 33 00 00 00 00 00 00 1a 00 +00 00 00 00 00 00 00 4a 00 00 00 00 00 00 00 00 +00 00 00 04 00 00 73 00 00 00 00 08 1d 04 00 00 +00 00 00 1e 34 14 00 00 07 0a 07 21 52 26 0c 00 +0b 0f 14 15 59 4f 02 1c 0c 13 21 13 34 34 00 0c +07 07 12 0c 0a 3a 7f 24 01 00 00 00 00 11 41 43 +00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 37 00 00 00 00 00 00 00 18 00 +00 00 00 00 00 07 00 14 00 00 08 00 00 25 00 3f +01 00 0f 0c 00 3d 00 2e 00 00 0f 05 00 25 4a 00 +00 00 06 00 10 23 00 22 00 00 05 10 13 1c 3b 00 +00 00 08 04 1e 15 2b 0c 00 00 00 00 2c 00 00 00 +00 00 00 03 2b 00 00 07 00 00 00 00 2c 00 00 30 +05 02 19 00 39 00 00 14 09 04 19 03 38 00 26 00 +00 00 00 01 00 00 00 00 00 00 00 00 00 00 43 00 +00 00 00 00 00 00 4b 4e 00 00 00 00 00 00 00 00 +00 00 00 06 00 00 00 00 00 05 00 14 23 1a 19 00 +04 07 04 2a 3d 23 00 00 09 0f 0c 1f 4c 2f 00 31 +0a 11 13 17 55 52 32 00 0a 11 1d 0c 3e 29 23 01 +00 04 09 00 12 1e 00 00 00 00 00 00 00 0d 24 7f +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f +00 00 00 00 00 00 18 00 00 00 00 00 00 0c 00 09 +07 00 0e 01 00 2d 00 00 00 00 10 00 00 0b 00 00 +03 00 09 00 0f 1c 00 00 00 03 0b 0b 12 19 00 0a +02 09 11 07 12 13 00 00 00 00 00 00 17 00 00 00 +00 01 00 00 19 05 00 32 01 09 00 00 17 05 40 7d +0d 0c 29 00 42 00 1e 77 0d 08 21 00 49 09 00 2e +00 00 07 00 23 00 5d 00 00 00 01 00 1e 00 5b 00 +00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 15 00 00 06 04 11 0c 08 2e 00 +03 09 0a 22 11 0f 00 06 0e 16 19 26 28 2c 00 6d +16 1f 1f 29 3f 53 2a 17 10 18 27 11 2c 2e 52 0a +00 03 0d 00 08 17 35 00 00 00 05 00 00 0d 00 00 +00 00 00 00 00 00 00 16 00 00 00 00 00 00 02 19 +00 00 00 00 00 00 00 4e 00 00 00 00 00 00 00 7f +00 00 00 00 00 02 00 46 00 00 00 00 00 11 00 69 +08 03 09 06 00 2b 26 00 04 02 08 00 01 0c 35 27 +00 00 00 00 11 0a 00 1a 00 00 09 07 12 12 00 00 +00 03 15 05 11 1b 00 00 00 00 02 00 0f 00 00 00 +00 00 00 00 00 05 00 00 00 02 07 00 00 15 00 0d +15 19 30 01 49 00 00 00 15 15 2a 0e 53 0d 1d 6d +0f 0a 1a 08 47 00 00 7f 06 00 07 00 32 00 20 3d +00 00 00 00 1f 00 00 00 00 00 00 00 09 00 55 5f +00 00 00 06 00 00 00 00 00 07 06 10 0b 00 00 10 +00 06 06 1a 0a 00 00 00 08 10 10 17 16 0f 0c 00 +0c 15 10 11 26 31 6a 23 04 0c 12 00 21 1c 0f 00 +00 00 06 00 01 17 00 16 00 00 0c 00 00 1b 00 0e +00 00 00 00 00 12 77 00 00 00 00 00 00 00 00 11 +00 00 00 00 00 00 00 00 00 00 00 0d 00 00 2c 13 +00 00 00 03 00 00 56 00 00 00 00 00 00 00 00 50 +0f 08 10 0e 00 2b 00 00 0f 0c 11 06 09 17 41 00 +09 05 08 00 05 25 03 65 0b 0f 1c 05 00 18 00 00 +09 11 26 05 00 27 57 00 00 02 11 00 08 07 25 46 +00 00 12 00 00 15 00 00 00 08 13 00 00 19 7c 2b +0c 0d 2b 03 24 00 00 57 05 04 19 05 1c 02 59 00 +05 01 08 01 1a 00 2b 45 00 00 00 00 10 00 7f 16 +00 00 00 00 1a 00 00 13 00 00 00 04 0e 00 00 00 +00 04 00 0e 19 00 00 79 00 07 08 08 21 17 00 00 +05 0d 0f 15 17 17 00 00 0c 14 15 1c 1a 29 70 00 +11 1b 18 0d 1d 4d 00 34 07 0c 13 00 15 3f 00 59 +00 05 10 00 06 31 7f 00 00 00 11 00 00 36 00 00 +00 00 08 00 00 27 00 06 00 00 00 02 00 00 1e 1d +00 00 00 08 00 0a 7f 00 00 00 00 20 00 00 00 00 +03 00 00 1b 00 01 00 1c 00 00 00 07 0c 00 15 00 +07 02 11 11 01 0e 4a 00 08 05 0d 13 02 00 1a 7f +05 05 05 01 00 1d 50 43 0c 13 23 13 00 12 00 00 +11 1b 31 11 00 2a 24 3e 0d 10 28 02 0f 21 00 00 +05 09 22 07 00 2a 45 30 05 09 1c 06 00 12 2c 00 +03 06 1f 00 14 00 00 20 00 00 0d 00 09 00 00 75 +00 00 00 00 03 00 19 00 00 00 00 00 00 00 00 09 +00 00 00 00 16 00 00 06 00 03 00 0e 03 07 00 00 +0e 14 14 1a 1a 1b 00 00 14 1d 27 11 25 2c 5a 38 +0e 15 23 0d 10 1e 00 37 13 17 29 17 14 3a 13 0f +16 1d 1f 11 2a 44 30 31 09 0d 10 00 24 32 12 00 +06 09 10 00 17 31 00 54 09 09 19 00 0a 3e 00 5b +06 03 19 06 00 37 32 00 00 00 0e 09 00 0b 00 0c +03 00 06 0b 00 0f 25 05 08 00 04 1b 00 00 00 00 +09 01 00 13 12 00 26 29 00 00 00 00 20 00 7e 48 +08 07 0e 06 18 00 00 00 06 05 0a 02 0a 00 00 27 +03 06 04 00 00 08 2b 75 09 0f 17 12 00 0b 00 28 +15 1f 2e 18 00 32 7f 36 0d 0f 22 09 00 20 00 00 +0e 13 2a 1e 00 33 2e 00 07 08 20 15 00 1c 25 00 +00 00 09 00 00 00 71 4b 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 14 00 1f 00 00 00 00 02 00 0e 00 24 +06 08 0d 09 0a 0c 7b 00 07 08 14 00 04 0d 00 30 +07 07 18 00 00 16 25 0a 06 02 15 00 00 2b 00 00 +0e 13 10 00 21 30 00 00 04 09 04 00 1f 2f 2b 11 +05 09 07 08 1f 2b 00 00 00 00 01 0d 09 15 23 4b +00 00 06 0f 00 16 75 7f 00 00 00 0a 00 00 00 00 +00 00 00 18 00 00 00 00 00 00 00 19 0b 00 00 00 +00 00 00 16 25 02 73 00 00 00 00 05 2c 00 00 00 +00 00 00 06 27 0f 00 0b 00 00 00 00 18 05 0c 00 +00 00 00 00 06 1c 00 00 00 01 02 04 00 0f 19 00 +04 0b 11 03 00 21 41 00 03 04 14 00 00 00 13 7f +06 0c 1a 13 00 19 57 14 04 03 16 10 00 08 01 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 56 +00 00 00 00 00 00 07 25 00 00 00 00 00 00 00 58 +00 00 00 00 00 02 00 00 02 05 03 01 00 1a 6e 00 +0c 0e 1b 0a 18 1b 00 7f 0e 0e 1c 00 21 1e 00 3b +0f 11 23 00 2a 23 00 03 0d 09 17 00 31 38 00 7f +13 17 13 00 4a 2b 7f 00 08 10 01 00 42 16 00 00 +07 11 07 06 3a 06 0b 00 00 03 00 05 21 00 02 15 +04 0a 0c 08 09 00 00 32 00 00 03 05 00 00 00 20 +05 00 0c 0d 00 00 31 13 06 00 06 16 0a 00 00 00 +03 00 00 1a 13 00 00 00 00 00 00 21 18 00 00 4e +01 00 01 13 19 00 26 00 00 00 00 09 07 00 00 15 +00 00 00 05 00 0d 00 00 01 05 0a 00 00 0d 00 00 +00 05 03 00 00 0b 00 04 00 00 01 00 00 00 00 53 +03 0b 0d 0c 00 09 0b 4b 00 00 00 08 00 00 00 2b +00 00 00 00 00 00 10 00 00 00 00 00 00 00 26 00 +00 00 00 00 00 00 00 7e 00 00 00 00 00 00 2b 00 +00 00 00 00 00 00 00 23 00 00 02 00 00 00 00 16 +01 00 15 08 00 00 00 00 00 00 11 00 02 12 36 0f +04 05 15 00 0b 24 00 39 07 01 10 02 19 3b 00 20 +11 13 10 0a 33 3a 68 00 0b 15 05 0b 27 23 11 00 +0d 15 0e 1f 27 07 00 11 01 02 08 10 15 00 00 46 +02 08 11 16 00 00 3b 28 01 02 0f 18 00 00 4b 2f +05 00 17 0f 00 00 22 7b 03 00 0d 0c 0f 00 2f 00 +02 03 02 1a 19 00 63 1c 03 05 05 22 25 00 00 00 +00 01 05 0e 1d 00 00 00 00 00 00 07 10 00 05 00 +00 00 00 03 00 0a 00 00 00 00 00 00 00 17 00 7c +00 00 00 00 00 08 00 00 00 00 00 00 00 12 07 3b +04 09 03 01 00 15 61 00 0a 0a 09 0f 00 0e 10 59 +00 00 00 0a 00 00 00 7f 00 07 00 0b 00 00 68 64 +02 09 01 04 00 07 15 00 00 05 06 05 00 12 19 00 +03 07 07 00 00 04 60 31 00 00 10 00 00 10 00 00 +02 00 1c 03 00 04 30 17 05 05 1b 00 02 13 45 1d +04 04 10 00 00 19 00 00 01 00 11 00 00 25 00 00 +0e 12 16 0c 1d 23 00 00 0d 1a 09 13 12 17 1b 00 +07 0f 07 19 0f 00 22 00 00 06 04 14 12 00 00 22 +01 0b 05 16 15 00 00 00 00 00 02 07 00 00 00 00 +00 00 0a 00 00 00 10 15 00 00 00 00 09 00 00 51 +00 00 00 00 01 00 00 00 00 00 00 00 09 00 0e 00 +00 00 00 00 0e 00 00 5e 00 00 00 00 0c 00 34 00 +00 00 00 00 00 00 00 00 01 01 0c 00 05 2d 50 00 +00 00 01 00 00 10 00 00 00 00 00 00 00 1a 00 14 +00 06 00 00 00 0b 00 42 08 0e 00 08 00 1a 2f 00 +00 00 00 0a 00 0e 00 00 00 00 00 0e 00 13 00 00 +07 0a 11 07 00 28 00 00 07 05 16 0e 00 29 00 00 +08 05 18 0c 00 15 7f 44 01 00 14 00 00 0a 00 7f +06 00 1b 0c 0b 00 00 1a 06 04 12 12 01 11 00 2d +03 06 09 00 00 10 1f 00 00 01 06 00 00 05 00 26 +0c 14 19 04 0b 11 00 00 0c 19 0f 0d 00 13 47 3f +04 0f 07 00 00 00 25 36 00 02 02 00 00 00 00 77 +02 06 02 03 15 00 1c 00 00 00 00 00 00 00 00 00 +00 00 04 00 04 00 00 00 00 00 00 00 17 00 00 00 +00 00 00 00 12 00 4d 00 00 00 00 00 0a 00 7f 00 +00 00 00 00 18 00 00 27 00 00 00 04 1f 07 46 2d +00 00 00 00 0b 0a 00 19 04 01 0c 02 1b 22 1c 00 +00 00 02 02 0d 01 00 20 00 00 00 00 00 13 3f 00 +00 00 00 01 00 00 16 00 07 0a 00 1b 0d 0a 00 19 +00 00 00 12 00 07 00 00 00 00 00 13 00 16 00 00 +06 09 15 0e 0b 37 00 43 09 04 1c 1c 10 36 66 00 +09 06 1e 1a 05 1d 00 00 09 06 21 09 1a 15 00 10 +06 01 21 07 2c 00 2d 06 09 0c 1c 16 22 23 06 00 +05 10 0f 00 16 11 00 7a 05 0f 11 00 0d 19 65 11 +0a 15 1f 02 15 20 00 00 0f 1e 1b 12 00 23 2d 0b +06 11 13 00 03 00 3d 00 01 06 12 00 00 00 00 30 +0a 10 12 14 23 00 1f 48 06 08 02 0f 0c 00 00 55 +03 02 0a 00 14 00 47 30 00 00 02 03 13 00 48 17 +00 00 00 10 0b 00 0b 6f 00 00 00 06 03 00 7e 00 +00 00 01 02 10 00 00 37 00 00 00 18 1a 00 00 00 +02 00 08 0b 0f 00 00 00 08 05 17 12 19 0e 25 00 +05 04 10 13 0a 00 19 00 01 00 00 06 00 1a 06 28 +00 00 00 00 00 00 28 55 00 02 00 0b 02 00 00 00 +00 00 00 14 00 22 00 26 00 00 00 1f 00 0f 64 00 +09 0d 1d 26 17 2e 00 7d 0a 09 26 2b 24 23 00 00 +09 07 23 22 16 0c 03 00 04 03 1a 0e 28 00 00 00 +00 00 14 00 27 00 00 5f 01 02 0a 01 14 07 1c 62 +00 08 00 00 00 08 22 16 05 12 12 00 00 0d 7f 00 +06 10 21 00 00 1c 00 00 0e 1b 25 10 00 1e 2a 1f +07 0f 1e 08 00 00 04 0b 07 09 1f 0c 00 00 00 78 +0f 0f 1a 1c 15 0c 19 5a 11 11 11 20 17 00 54 00 +10 0f 17 07 2d 00 7f 24 0b 10 13 07 2a 00 00 69 +05 0d 0c 09 21 00 0d 05 00 01 00 00 21 00 6c 02 +00 08 0e 00 22 00 00 00 07 0b 0e 18 25 00 1a 0e +04 02 09 08 11 00 47 7f 09 09 11 0f 1b 14 4b 05 +09 0c 13 12 00 0f 00 00 02 04 00 03 00 1a 6e 74 +00 00 00 00 00 00 16 1f 02 09 00 0f 00 13 00 00 +00 00 00 11 00 28 00 0d 00 00 00 1c 00 17 00 00 +07 0b 1e 35 1b 3a 15 00 0b 09 2a 38 25 29 06 00 +00 00 18 24 0e 00 65 55 01 00 16 12 29 00 1e 31 +00 00 05 00 24 00 00 00 00 00 00 00 11 00 00 00 +00 00 00 00 00 00 0f 00 02 13 0d 00 02 11 0e 00 +01 0b 18 00 00 0d 4e 43 06 13 1d 07 00 0d 2e 7f +05 10 1e 00 00 00 0f 00 01 03 0e 00 00 00 37 00 +07 07 0a 05 15 04 69 00 0a 0a 07 07 1d 00 00 48 +0c 0d 0d 00 41 00 2a 00 06 09 04 00 2f 00 24 2d +07 0d 0e 03 1f 00 18 39 00 00 00 00 18 00 13 59 +05 0c 0b 00 23 00 2a 00 08 08 0e 17 1b 00 70 00 +00 00 05 01 03 00 00 18 04 02 0f 16 1a 00 00 18 +05 06 11 0e 00 02 4f 7f 00 00 03 05 00 00 16 00 +00 00 00 00 02 00 00 2b 02 03 01 11 05 00 00 00 +05 0b 11 13 00 38 28 7c 07 08 14 2b 09 33 00 00 +12 15 2f 3d 15 48 77 00 0d 07 2e 38 18 27 1a 00 +00 00 13 26 0d 02 02 2f 00 00 12 19 26 00 0e 08 +00 00 00 00 0b 00 00 00 00 00 00 03 03 04 00 00 +00 01 00 00 04 04 00 04 08 17 0a 00 09 14 00 48 +0a 16 19 02 09 16 00 00 0e 1a 1b 14 00 0e 36 5d +0c 15 21 08 16 00 00 00 06 08 11 0a 04 00 22 7f +0e 0c 14 1a 1e 03 00 00 0f 0e 0f 1a 1f 00 00 7e +0b 0c 0e 01 2d 00 00 00 0b 13 10 0a 1a 00 70 00 +0a 16 17 0c 07 00 24 53 00 05 03 00 03 00 00 00 +0b 15 11 11 12 00 07 17 08 09 0d 22 02 00 00 16 +00 00 00 0e 00 00 04 16 00 00 00 16 00 00 00 00 +00 00 00 08 00 00 6c 00 00 00 00 0e 00 00 49 51 +01 03 00 12 0d 00 26 00 0d 0b 0f 29 17 00 34 1a +00 08 07 0b 00 06 38 00 04 0a 09 24 08 0f 3c 00 +0f 14 1f 35 1f 33 63 29 0e 0a 26 2e 19 1c 00 28 +04 00 0b 25 0c 0a 00 00 00 00 0e 11 2a 00 23 25 +00 00 02 00 11 00 00 44 00 00 00 00 0c 0f 1f 00 +00 00 00 00 0f 14 00 00 00 09 00 00 0f 24 2e 00 +00 02 02 00 0f 22 21 00 00 06 07 04 07 06 7a 00 +01 09 11 0d 14 00 19 15 01 01 0e 17 0b 00 07 00 +0f 0e 1c 2d 27 06 00 00 14 17 1b 30 1c 00 00 00 +18 1b 18 26 1c 1f 00 02 12 17 16 1e 0c 1e 00 49 +10 1a 1c 19 04 13 2a 52 00 06 08 00 00 00 1b 2c +0d 17 18 11 06 04 00 00 03 06 0f 1d 00 00 00 00 +00 00 00 03 00 00 35 6b 00 04 00 0b 00 00 7f 45 +07 0e 01 02 00 00 4f 00 00 03 00 03 00 00 00 57 +05 0d 00 00 07 00 06 00 0e 11 10 14 0c 00 00 00 +6c 7f 1e 1e diff --git a/pi/pinout.jpeg b/pi/pinout.jpeg new file mode 100644 index 0000000..f4830e3 Binary files /dev/null and b/pi/pinout.jpeg differ diff --git a/pi/spi_test.py b/pi/spi_test.py new file mode 100644 index 0000000..75b297a --- /dev/null +++ b/pi/spi_test.py @@ -0,0 +1,210 @@ +MAX_ADDRESS = 1024 * 128 +MAX_DATA = 1024 +PRINT_ACK = False # print the ack waits.... + +# setup SPI +import spidev +spi = spidev.SpiDev() +spi.open(0, 0) +spi.max_speed_hz = 8000000 +spi.mode = 0b11 + +# toggle CS pin manually as writing and reading in the same cycle +import RPi.GPIO as GPIO +GPIO.setwarnings(False) +GPIO.setmode(GPIO.BOARD) +cs_pin = 22 +GPIO.setup(cs_pin, GPIO.OUT) +GPIO.output(cs_pin, GPIO.HIGH) + +# utility functions +def get_cursor_low_high(cursor): + cursor_low = cursor & 0xFF + cursor_high = cursor >> 8 + return cursor_low, cursor_high + +def chunks(l, n): + """Yield successive n-sized chunks from l.""" + for i in range(0, len(l), n): + yield l[i:i + n] + +def spi_start(): + GPIO.output(cs_pin, GPIO.LOW) + +def spi_stop(): + GPIO.output(cs_pin, GPIO.HIGH) + +# core returns 0xFF as a busy signal. Wait till returns 0 +def get_ack(print_ack=PRINT_ACK): + if print_ack: + print("ack "), + + count = 0 + while True: + data = spi.readbytes(1) + # mlaccel core returns 0 when working, 0xFF when done + if data == [0]: + break; + # wait up to 10 cycles before giving up + count += 1 + if print_ack and (count % 10 == 0): + print("."), + + if print_ack: + print("") + +def spi_wait(): + spi.readbytes(1) + +# send an amount of data +def send_data(cursor, data): + assert cursor <= MAX_ADDRESS + # send the data to the buffer + d_len = len(data) + assert d_len <= MAX_DATA + spi_start() + spi.xfer([0x21]) + spi.xfer(data) + spi_stop() + + # get the buffer written to memory + spi_start() + cursor_low, cursor_high = get_cursor_low_high(cursor >> 1) + spi.xfer([0x23, cursor_low, cursor_high, d_len >> 2]) + spi_wait() + # wait for data to be written + get_ack() + spi_stop() + +# read an amount of data +def get_data(cursor, d_len): + assert cursor <= MAX_ADDRESS + assert d_len <= MAX_DATA + # write the address where we want to read + spi_start() + cursor_low, cursor_high = get_cursor_low_high(cursor >> 1) + spi.xfer([0x24, cursor_low, cursor_high, d_len >> 2]) + spi_wait() + # wait for data to become ready + get_ack() + spi_stop() + + # read it + spi_start() + spi.xfer([0x22]) + spi_wait() + data = spi.readbytes(d_len) + spi_stop() + return data + +# start and wait for kernel +def start_kernel(): + spi_start() + spi.xfer([0x25]) + spi.xfer([0x00, 0x00]) + spi_stop() + +def wait_for_kernel(): + spi_start() + spi.xfer([0x20]) + spi_wait() + get_ack(print_ack=True) + spi_stop() + +# random write/read test +def random_write_read_test(): + import random + count = 0 + while True: + print(count) + count += 1 + for cursor in range(255): + rand_data = [ random.randint(0, 255), random.randint(0,255) ] + send_data(cursor, rand_data) + rx_data = get_data(cursor, len(rand_data)) + assert(rx_data == rand_data) + +# check ability to write and read up to 1024 bytes +def long_data_test(num_tests, chunk_len): + data = range(chunk_len) + data = [d % 256 for d in data ] + + print("writing") + print("-" * 50) + cursor = 0 + for t in range(num_tests): + print("uploading %d bytes to %05x" % (chunk_len, cursor)) + send_data(cursor, data) + cursor += chunk_len + + print("reading") + print("-" * 50) + cursor = 0 + for cursor in range(num_tests): + print("downloading %d bytes from %05x" % (chunk_len, cursor)) + rx_data = get_data(cursor, chunk_len) + assert(rx_data == data) + cursor += chunk_len + + print("success") + + +if __name__ == '__main__': + chunk_size = 1024 + assert(chunk_size <= MAX_DATA) + +# long_data_test(128, chunk_size) +# exit(0) + + # prepare data + data_in = [] + with open("demo.hex") as data_in_fh: + data_in_fh.readline() + for line in data_in_fh.readlines(): + bytes_4 = [int(b, 16) for b in line.strip().split(' ')] + data_in += bytes_4 + + # upload kernel + print("uploading demo kernel:") + cursor = 0 + for chunk in chunks(data_in, chunk_size): + chunk_len = len(chunk) + print("> uploading %4d bytes to %05x" % (chunk_len, cursor)) + send_data(cursor, chunk) + cursor += chunk_len + + # check data is valid + print("readback:") + cursor = 0 + for chunk in chunks(data_in, chunk_size): + chunk_len = len(chunk) + print("< downloading %4d bytes from %05x" % (chunk_len, cursor)) + data = get_data(cursor, chunk_len) + assert(data == chunk) + cursor += chunk_len + + # run and wait for the kernel to finish + print("start kernel") + start_kernel() + print("wait kernel") + wait_for_kernel() + + # prepare comparison data + data_out = [] + with open("demo_out.hex") as data_out_fh: + data_out_fh.readline() + for line in data_out_fh.readlines(): + bytes_16 = [int(b, 16) for b in line.strip().split(' ')] + data_out += bytes_16 + + # check results are valid + print("checking results:") + cursor = 0x00010000 + for chunk in chunks(data_out, chunk_size): + chunk_len = len(chunk) + print("< downloading %4d bytes from %05x" % (chunk_len, cursor)) + data = get_data(cursor, chunk_len) + assert(data == chunk) + cursor += chunk_len + + print("success") diff --git a/rtl/Makefile b/rtl/Makefile index 137c3ca..085baa4 100644 --- a/rtl/Makefile +++ b/rtl/Makefile @@ -5,10 +5,17 @@ all: testbench sed '/^TRACE/ ! d; s/^[^:]*: //;' < testbench.log > testbench.trace cmp ../sim/demo.trace testbench.trace -testbench: testbench.v top.v memory.v sequencer.v compute.v - iverilog -DTRACE -s testbench -o testbench testbench.v top.v memory.v sequencer.v compute.v $(shell yosys-config --datdir/ice40/cells_sim.v) +formal_spi: spi_client.v + sby -f spi.sby + +testbench_simple: testbench_simple.v top.v memory.v sequencer.v compute.v spi_client.v + iverilog -DTRACE -s testbench -o testbench_simple testbench_simple.v top.v memory.v sequencer.v compute.v spi_client.v $(shell yosys-config --datdir/ice40/cells_sim.v) + vvp -N testbench_simple + +testbench: testbench.v top.v memory.v sequencer.v compute.v spi_client.v + iverilog -DTRACE -s testbench -o testbench testbench.v top.v memory.v sequencer.v compute.v spi_client.v $(shell yosys-config --datdir/ice40/cells_sim.v) clean: - rm -f testbench testbench.vcd testbench.log testbench.trace + rm -f testbench testbench_simple testbench.vcd testbench.log testbench.trace .PHONY: all clean diff --git a/rtl/cmd_filter.txt b/rtl/cmd_filter.txt new file mode 100644 index 0000000..22a8cac --- /dev/null +++ b/rtl/cmd_filter.txt @@ -0,0 +1,7 @@ +20 = status +21 = wbuf +22 = rbuf +23 = wmem +24 = rmem +25 = run +26 = stop diff --git a/rtl/spi.gtkwave b/rtl/spi.gtkwave new file mode 100644 index 0000000..9ed44a7 --- /dev/null +++ b/rtl/spi.gtkwave @@ -0,0 +1,161 @@ +[*] +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Fri Nov 16 17:18:13 2018 +[*] +[dumpfile] "/home/matt/work/fpga/mlaccel/rtl/sspi/testbench.vcd" +[dumpfile_mtime] "Fri Nov 16 17:17:10 2018" +[dumpfile_size] 1547642 +[savefile] "/home/matt/work/fpga/mlaccel/rtl/sspi/spi.gtkwave" +[timestart] 103746 +[size] 1917 1020 +[pos] -1 -1 +*-8.000000 104454 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] testbench. +[treeopen] testbench.uut. +[treeopen] testbench.uut.mem. +[treeopen] testbench.uut.mem.ram[0]. +[sst_width] 253 +[signals_width] 492 +[sst_expanded] 1 +[sst_vpaned_height] 306 +@28 +testbench.clock +@2024 +^1 /home/matt/work/fpga/mlaccel/rtl/sspi/../../../../../../../tmp/../home/matt/work/fpga/mlaccel/rtl/sspi/../../../../../../../tmp/../home/matt/work/fpga/mlaccel/rtl/sspi/state_filter.txt +testbench.uut.state[5:0] +@22 +testbench.uut.buffer_ptr[10:0] +testbench.uut.dout_data[7:0] +@8024 +testbench.cursor +@28 +testbench.uut.reset +testbench.uut.spi.spi_csb_di +testbench.spi_clk +@22 +testbench.uut.dout_data[7:0] +@28 +testbench.uut.din_start +testbench.uut.spi.di_start +testbench.uut.din_valid +testbench.uut.spi_active +@22 +testbench.uut.din_data[7:0] +@29 +testbench.xfer_wait_start +@28 +testbench.xfer_read_start +@c00022 +testbench.xfer[7:0] +@28 +(0)testbench.xfer[7:0] +(1)testbench.xfer[7:0] +(2)testbench.xfer[7:0] +(3)testbench.xfer[7:0] +(4)testbench.xfer[7:0] +(5)testbench.xfer[7:0] +(6)testbench.xfer[7:0] +(7)testbench.xfer[7:0] +@1401200 +-group_end +@28 +testbench.spi_mosi_reg +testbench.uut.spi.spi_csb_di +testbench.spi_miso +@200 +- +@28 +testbench.uut.dout_valid +testbench.uut.dout_ready +testbench.uut.spi.dout_busy +@c00024 +testbench.uut.spi.do_data[7:0] +@28 +(0)testbench.uut.spi.do_data[7:0] +(1)testbench.uut.spi.do_data[7:0] +(2)testbench.uut.spi.do_data[7:0] +(3)testbench.uut.spi.do_data[7:0] +(4)testbench.uut.spi.do_data[7:0] +(5)testbench.uut.spi.do_data[7:0] +(6)testbench.uut.spi.do_data[7:0] +(7)testbench.uut.spi.do_data[7:0] +@1401200 +-group_end +@c00024 +testbench.uut.spi.do_bit[2:0] +@28 +(0)testbench.uut.spi.do_bit[2:0] +(1)testbench.uut.spi.do_bit[2:0] +(2)testbench.uut.spi.do_bit[2:0] +@1401200 +-group_end +@28 +testbench.uut.spi.spi_miso +@200 +- +@c00022 +testbench.uut.spi.din_data[7:0] +@28 +(0)testbench.uut.spi.din_data[7:0] +(1)testbench.uut.spi.din_data[7:0] +(2)testbench.uut.spi.din_data[7:0] +(3)testbench.uut.spi.din_data[7:0] +(4)testbench.uut.spi.din_data[7:0] +(5)testbench.uut.spi.din_data[7:0] +(6)testbench.uut.spi.din_data[7:0] +(7)testbench.uut.spi.din_data[7:0] +@1401200 +-group_end +@24 +testbench.uut.spi.di_bit[2:0] +@c00028 +testbench.uut.spi.di_data[7:0] +@28 +(0)testbench.uut.spi.di_data[7:0] +(1)testbench.uut.spi.di_data[7:0] +(2)testbench.uut.spi.di_data[7:0] +(3)testbench.uut.spi.di_data[7:0] +(4)testbench.uut.spi.di_data[7:0] +(5)testbench.uut.spi.di_data[7:0] +(6)testbench.uut.spi.di_data[7:0] +(7)testbench.uut.spi.di_data[7:0] +@1401200 +-group_end +@28 +testbench.uut.spi_clk +testbench.uut.spi.spi_mosi +@200 +- +@28 +testbench.uut.spi.spi_clk_di +testbench.uut.spi.glitch_guard_clock_q0 +testbench.uut.spi.glitch_guard_negedge +testbench.uut.spi.glitch_guard_posedge +testbench.uut.spi.clk_q1 +testbench.uut.spi.clk_q2 +@200 +- +@24 +testbench.uut.spi.di_bit[2:0] +@22 +testbench.uut.spi.glitch_guard_di_bit_q0[3:0] +testbench.uut.spi.glitch_guard_di_bit[3:0] +@200 +- +@24 +testbench.uut.spi.do_bit[2:0] +@22 +testbench.uut.spi.glitch_guard_do_bit_q0[3:0] +testbench.uut.spi.glitch_guard_do_bit[3:0] +@200 +- +@22 +testbench.uut.mem.addr0[13:0] +testbench.uut.mem.addr[15:0] +testbench.uut.mem.rdata[63:0] +testbench.uut.mem.wdata[63:0] +testbench.uut.state[5:0] +testbench.uut.buffer_ptr[10:0] +testbench.uut.mem.wen[7:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/rtl/spi.sby b/rtl/spi.sby new file mode 100644 index 0000000..4d2d555 --- /dev/null +++ b/rtl/spi.sby @@ -0,0 +1,14 @@ +[options] +mode prove +multiclock on +depth 20 + +[engines] +smtbmc + +[script] +read_verilog -formal spi_client.v +prep -top spi_client + +[files] +spi_client.v diff --git a/rtl/spi_client.v b/rtl/spi_client.v new file mode 100644 index 0000000..345c652 --- /dev/null +++ b/rtl/spi_client.v @@ -0,0 +1,288 @@ +`default_nettype none +module spi_client ( + input i_clock, + input i_reset, + output o_active, // high whenever chip selected + + input i_spi_clk, // spi clock + input i_spi_cs_n, // spi chip select, low to select + + output reg o_miso, // output to master + input i_mosi, // input from master + + output reg o_data_in_valid, // data from master is ready to read on the data_in_data reg + output reg o_data_in_start, // high for first byte received after cs goes low + output reg [7:0] o_data_in_data, // data register from master + + input i_data_out_valid, // data in the input data bus is valid to read + output reg o_data_out_ready, // data has been registered + input [7:0] i_data_out_data // input data to send to the master +); + + + assign o_active = !i_spi_cs_n; + + // data coming from master goes here + reg [2:0] in_bit = 0; + reg [7:0] data_in = 0; + + // data to send goes here + reg [2:0] out_bit = 0; + reg [7:0] data_out = 0; + // copy of data_out for the spi_clock domain + reg [7:0] data_out_spi = 0; + reg [7:0] data_in_spi = 0; + + + reg first_byte = 0; + reg start_status = 0; // registers data_in_start + + + always @(posedge i_spi_clk, posedge i_spi_cs_n) begin + if(i_spi_cs_n) begin // reset state + in_bit <= 0; + first_byte <= 1; + end else begin // receiving data + data_in[3'd7-in_bit] <= i_mosi; + in_bit <= in_bit + 1; + if(in_bit == 7) begin + data_in_spi <= { data_in[7:1], i_mosi }; + first_byte <= 0; + end + end + end + + always @(negedge i_spi_clk, posedge i_spi_cs_n) begin + if(i_spi_cs_n) begin // reset state + out_bit <= 0; + end else begin + if(out_bit == 7) // get a local copy of the data to send out - guaranteed stable + data_out_spi <= data_out; + o_miso <= data_out_spi[3'd7-out_bit]; + out_bit <= out_bit + 1; + end + end + + localparam DATA_IN_WAIT = 0; + localparam DATA_IN_RX = 1; + localparam DATA_IN_READY = 2; + localparam DATA_IN_ENDSTATE = 3; + reg [$clog2(DATA_IN_ENDSTATE)-1:0] data_in_state = DATA_IN_WAIT; + + localparam DATA_OUT_WAIT = 0; + localparam DATA_OUT_TX = 1; + localparam DATA_OUT_ENDSTATE = 2; + reg [$clog2(DATA_OUT_ENDSTATE)-1:0] data_out_state = DATA_OUT_WAIT; + + // clock domain crossing with 2 flip flops and one for what happened one clock ago + reg out_bit_clock, out_bit_clock_past, out_bit_clock_pipe; + reg in_bit_clock, in_bit_clock_past, in_bit_clock_pipe; + reg fb_clock, fb_clock_past, fb_clock_pipe; + + initial begin + { out_bit_clock_past, out_bit_clock, out_bit_clock_pipe } = 0; + { in_bit_clock_past, in_bit_clock, in_bit_clock_pipe } = 0; + { fb_clock, fb_clock_past, fb_clock_pipe } = 3'b111; + end + + always @(posedge i_clock) begin + { out_bit_clock_past, out_bit_clock, out_bit_clock_pipe } <= { out_bit_clock, out_bit_clock_pipe, out_bit[2] }; + { in_bit_clock_past, in_bit_clock, in_bit_clock_pipe } <= { in_bit_clock, in_bit_clock_pipe, in_bit == 7 }; + { fb_clock_past, fb_clock, fb_clock_pipe } <= { fb_clock, fb_clock_pipe, first_byte }; + end + + initial begin + data_in_state <= DATA_IN_WAIT; + data_out_state <= DATA_OUT_WAIT; + o_data_in_start <= 0; + o_data_out_ready <= 0; + start_status <= 0; + end + + always @(posedge i_clock) begin + if(i_reset) begin + data_in_state <= DATA_IN_WAIT; + data_out_state <= DATA_OUT_WAIT; + o_data_in_start <= 0; + o_data_out_ready <= 0; + start_status <= 0; + end + else begin + + case(data_in_state) + DATA_IN_WAIT: begin + start_status <= fb_clock; + o_data_in_valid <= 0; + if(in_bit_clock == 1) + data_in_state <= DATA_IN_RX; + end + DATA_IN_RX: begin + if(in_bit_clock == 0) + data_in_state <= DATA_IN_READY; + end + DATA_IN_READY: begin + o_data_in_valid <= 1; + o_data_in_start <= start_status; + o_data_in_data <= data_in_spi; + data_in_state <= DATA_IN_WAIT; + end + endcase + + case(data_out_state) + DATA_OUT_WAIT: begin + if({out_bit_clock, out_bit_clock_past} == 2'b10) + if(i_data_out_valid) begin + data_out <= i_data_out_data; + o_data_out_ready <= 1; + data_out_state <= DATA_OUT_TX; + end + end + DATA_OUT_TX: begin + o_data_out_ready <= 0; + if({out_bit_clock, out_bit_clock_past} == 2'b01) + data_out_state <= DATA_OUT_WAIT; + end + + endcase + end + end + +`ifdef FORMAL + reg [3:0] f_clk_counter; + initial f_clk_counter = 0; + + // ASSUMPTIONS + + initial assume(i_reset); + initial assume(i_spi_cs_n); + + // past valid signal + reg f_past_valid = 0; + always @($global_clock) + f_past_valid <= 1'b1; + + // stop reset from happening after start + always @($global_clock) + if(f_past_valid) + assume(i_reset == 0); + + // fix sys clock + wire [7:0] f_sys_step = 8'h40; + reg [7:0] f_sys_counter; + reg [7:0] f_spi_counter; + + // system clock + always @($global_clock) begin + f_sys_counter <= f_sys_counter + f_sys_step; + assume ( i_clock == f_sys_counter [7]); + end + + // spi clock + // allow spi clock to be around 1/4 sys clock + (* anyconst *) wire [7:0] f_spi_step; + always @(*) + assume ((f_spi_step > 8'h05) && (f_spi_step <= 8'h15)); + + // spi clock if spi_cs_n + always @($global_clock) begin + f_spi_counter <= f_spi_counter + f_spi_step; + assume ( i_spi_cs_n || i_spi_clk == f_spi_counter [7]); + end + + // inputs only can change on system clock + always @($global_clock) + if(f_past_valid && !$rose(i_clock)) begin + assume($stable(i_data_out_valid)); + assume($stable(i_data_out_data)); + assume($stable(i_reset)); + end + + // SPI assumptions + // mosi is stable as spi clock rises + always @($global_clock) + if(f_past_valid && i_spi_clk) begin + assume($stable(i_mosi)); + end + + // if no clock, no chip select + always @(*) + if(!i_spi_clk) + assume(!i_spi_cs_n); + + // no chip select, no clock + always @($global_clock) + if(f_past_valid) + if($rose(i_spi_cs_n) || $fell(i_spi_cs_n)) + assume($stable(i_spi_clk) && i_spi_clk); + + // controller behaves by keeping valid line high and not changing data until we are ready + always @(posedge i_clock) + if(f_past_valid) + if($past(i_data_out_valid) && $past(!o_data_out_ready)) + assume($stable(i_data_out_data) && i_data_out_valid); + + // ensure chip select is held long enough to be effective + reg [2:0] chip_select_count = 0; + always @($global_clock) + if(i_spi_cs_n == 1 && chip_select_count < 7) + chip_select_count <= chip_select_count + 1; + else if(i_spi_cs_n == 0) + chip_select_count <= 0; + + always @($global_clock) + if(f_past_valid) + if(chip_select_count < 3) + assume(!$fell(i_spi_cs_n)); + + + // ASSERTIONS + + + // assert everything is zeroed on the reset signal + always @($global_clock) + if (f_past_valid) + if ($past(i_reset) && $rose(i_clock)) begin + assert(data_out_state == DATA_OUT_WAIT); + assert(data_in_state == DATA_IN_WAIT); + assert(o_data_in_start == 0); + end + + // spi counters are reset on cs_n + always @($global_clock) + if (f_past_valid) + if ($past(i_spi_cs_n) && $stable(i_spi_clk)) begin + assert(in_bit == 0); + assert(out_bit == 0); + assert(first_byte == 1); + end + + // counters increase + always @($global_clock) begin + if (f_past_valid) begin + if(!i_spi_cs_n && $rose(i_spi_clk)) + assert(in_bit != $past(in_bit)); + if(!i_spi_cs_n && $fell(i_spi_clk)) + assert(out_bit != $past(out_bit)); + end + end + + // state machines: so simple just make sure they stay bounded + always @($global_clock) begin + assert(data_out_state < DATA_OUT_ENDSTATE); + assert(data_in_state < DATA_IN_ENDSTATE); + end + + // CDC ensure data_out doesn't change while it's being copied to data_out_spi + always @($global_clock) + if(f_past_valid) + if(out_bit == 6 || out_bit == 7) + assert($stable(data_out)); + + // CDC: capturing data from mosi and putting into controller's clock domain + always @($global_clock) + if(f_past_valid) + if($rose(i_clock) && data_in_state == DATA_IN_READY) + assert($stable(data_in_spi)); + +`endif +endmodule diff --git a/rtl/spi_data_in_filter.txt b/rtl/spi_data_in_filter.txt new file mode 100644 index 0000000..d3c8846 --- /dev/null +++ b/rtl/spi_data_in_filter.txt @@ -0,0 +1,3 @@ +0 = WAIT +1 = RX +2 = READY diff --git a/rtl/spi_data_out_filter.txt b/rtl/spi_data_out_filter.txt new file mode 100644 index 0000000..a67ef83 --- /dev/null +++ b/rtl/spi_data_out_filter.txt @@ -0,0 +1,2 @@ +0 = WAIT +1 = TX diff --git a/rtl/spi_formal.gtkw b/rtl/spi_formal.gtkw new file mode 100644 index 0000000..0665db5 --- /dev/null +++ b/rtl/spi_formal.gtkw @@ -0,0 +1,54 @@ +[*] +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Mon Nov 19 16:36:01 2018 +[*] +[dumpfile] "/home/matt/work/fpga/mlaccel/rtl/spi/engine_0/trace_induct.vcd" +[dumpfile_mtime] "Mon Nov 19 16:31:51 2018" +[dumpfile_size] 8257 +[savefile] "/home/matt/work/fpga/mlaccel/rtl/spi_formal.gtkw" +[timestart] 0 +[size] 1774 1134 +[pos] -295 114 +*-6.258204 190 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 253 +[signals_width] 519 +[sst_expanded] 1 +[sst_vpaned_height] 332 +@c00200 +-spi_client.f_clk_counter +@1401200 +-group_end +@28 +spi_client.i_clock +spi_client.i_spi_clk +spi_client.i_mosi +spi_client.i_reset +spi_client.i_spi_cs_n +@24 +spi_client.chip_select_count[2:0] +@200 +- +@22 +spi_client.i_data_out_data[7:0] +@28 +spi_client.i_data_out_valid +@24 +spi_client.out_bit[2:0] +@22 +spi_client.data_out[7:0] +@28 +spi_client.data_out_state +@200 +- +@23 +spi_client.data_in[7:0] +@24 +spi_client.in_bit[2:0] +@28 +spi_client.data_in_state[1:0] +spi_client.o_data_in_start +spi_client.i_spi_cs_n +spi_client.spi_cs_n_clock_pipe +spi_client.spi_cs_n_clock +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/rtl/spitest.gtkw b/rtl/spitest.gtkw new file mode 100644 index 0000000..c8c77d3 --- /dev/null +++ b/rtl/spitest.gtkw @@ -0,0 +1,102 @@ +[*] +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Wed Nov 21 17:06:54 2018 +[*] +[dumpfile] "/home/matt/work/fpga/mlaccel/rtl/testbench.vcd" +[dumpfile_mtime] "Wed Nov 21 12:09:29 2018" +[dumpfile_size] 587223476 +[savefile] "/home/matt/work/fpga/mlaccel/rtl/spitest.gtkw" +[timestart] 0 +[size] 2512 1573 +[pos] -2513 -1 +*-18.000000 903682 1015310 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] testbench. +[treeopen] testbench.uut. +[treeopen] testbench.uut.mem.ram[0]. +[sst_width] 303 +[signals_width] 456 +[sst_expanded] 1 +[sst_vpaned_height] 500 +@28 +testbench.uut.reset +@8022 +testbench.cursor +@24 +testbench.len +@8022 +testbench.i +@28 +testbench.uut.clock +@22 +testbench.xfer_send_byte.data[7:0] +@c00022 +testbench.xfer[7:0] +@28 +(0)testbench.xfer[7:0] +(1)testbench.xfer[7:0] +(2)testbench.xfer[7:0] +(3)testbench.xfer[7:0] +(4)testbench.xfer[7:0] +(5)testbench.xfer[7:0] +(6)testbench.xfer[7:0] +(7)testbench.xfer[7:0] +@1401200 +-group_end +@22 +testbench.uut.din_data[7:0] +@28 +testbench.xfer_read_start +@29 +testbench.xfer_wait_start +@200 +- +- +@28 +testbench.uut.spi.i_spi_clk +testbench.uut.spi.i_spi_cs_n +testbench.uut.spi.i_mosi +testbench.uut.spi.o_miso +@200 +- +@28 +testbench.uut.spi.o_active +@200 +- +@24 +testbench.uut.spi.in_bit[2:0] +@22 +testbench.uut.spi.data_in[7:0] +testbench.uut.spi.data_in_spi[7:0] +testbench.uut.spi.o_data_in_data[7:0] +@2022 +^1 /home/matt/work/fpga/mlaccel/rtl/../../../../../../tmp/../home/matt/work/fpga/mlaccel/rtl/spi_data_in_filter.txt +testbench.uut.spi.data_in_state[1:0] +@200 +- +@28 +testbench.uut.spi.o_data_in_start +testbench.uut.spi.o_data_in_valid +testbench.uut.spi.start_status +testbench.uut.spi.in_bit_clock +testbench.uut.spi.in_bit_clock_past +@200 +- +@2024 +^1 /home/matt/work/fpga/mlaccel/rtl/../../../../../../tmp/../home/matt/work/fpga/mlaccel/rtl/spi_data_in_filter.txt +testbench.uut.spi.data_out_state +@28 +testbench.uut.spi.i_data_out_valid +testbench.uut.spi.o_data_out_ready +@22 +testbench.uut.spi.i_data_out_data[7:0] +testbench.uut.spi.data_out[7:0] +@24 +testbench.uut.spi.out_bit[2:0] +@22 +testbench.uut.spi.data_out_spi[7:0] +@28 +testbench.uut.spi.out_bit_clock +testbench.uut.spi.out_bit_clock_past +testbench.uut.spi.o_miso +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/rtl/spitest.gtkwave b/rtl/spitest.gtkwave new file mode 100644 index 0000000..99cb1e8 --- /dev/null +++ b/rtl/spitest.gtkwave @@ -0,0 +1,57 @@ +[*] +[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI +[*] Tue Nov 20 18:15:20 2018 +[*] +[dumpfile] "/home/mattvenn/work/fpga/mlaccel/rtl/testbench.vcd" +[dumpfile_mtime] "Tue Nov 20 18:08:14 2018" +[dumpfile_size] 4888613 +[savefile] "/home/mattvenn/work/fpga/mlaccel/rtl/spitest.gtkwave" +[timestart] 38200 +[size] 1393 754 +[pos] -1 -1 +*-11.000000 44420 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] testbench. +[treeopen] testbench.uut. +[sst_width] 263 +[signals_width] 252 +[sst_expanded] 1 +[sst_vpaned_height] 209 +@28 +testbench.clock +@8022 +testbench.cursor[31:0] +@22 +testbench.xfer[7:0] +@28 +testbench.xfer_wait_start +testbench.xfer_read_start +@200 +- +@28 +testbench.uut.spi.i_spi_clk +testbench.uut.spi.i_spi_cs_n +@200 +-mosi +@28 +testbench.uut.spi.i_mosi +@22 +testbench.uut.spi.o_data_in_data[7:0] +@28 +testbench.uut.spi.o_data_in_start +testbench.uut.spi.o_data_in_valid +@22 +testbench.uut.din_data[7:0] +@200 +- +-miso +@28 +testbench.uut.spi.o_miso +@22 +testbench.uut.spi.i_data_out_data[7:0] +@23 +testbench.uut.dout_data[7:0] +@28 +testbench.uut.spi.i_data_out_valid +testbench.uut.spi.o_data_out_ready +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/rtl/spitest_simple.gtkw b/rtl/spitest_simple.gtkw new file mode 100644 index 0000000..3571862 --- /dev/null +++ b/rtl/spitest_simple.gtkw @@ -0,0 +1,69 @@ +[*] +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Mon Nov 19 17:11:30 2018 +[*] +[dumpfile] "/home/matt/work/fpga/mlaccel/rtl/testbench.vcd" +[dumpfile_mtime] "Mon Nov 19 17:08:52 2018" +[dumpfile_size] 149967 +[savefile] "/home/matt/work/fpga/mlaccel/rtl/spitest.gtkw" +[timestart] 10499 +[size] 1649 1029 +[pos] 317 470 +*-10.000000 13880 1015310 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] testbench. +[treeopen] testbench.uut. +[treeopen] testbench.uut.mem.ram[0]. +[sst_width] 303 +[signals_width] 456 +[sst_expanded] 1 +[sst_vpaned_height] 309 +@28 +testbench.uut.reset +@8022 +testbench.cursor +@28 +testbench.uut.clock +@22 +testbench.xfer_send_byte.data[7:0] +@c00022 +testbench.xfer[7:0] +@28 +(0)testbench.xfer[7:0] +(1)testbench.xfer[7:0] +(2)testbench.xfer[7:0] +(3)testbench.xfer[7:0] +(4)testbench.xfer[7:0] +(5)testbench.xfer[7:0] +(6)testbench.xfer[7:0] +(7)testbench.xfer[7:0] +@1401200 +-group_end +@200 +- +- +@28 +testbench.uut.spi.i_spi_clk +testbench.uut.spi.i_spi_cs_n +testbench.uut.spi.i_mosi +testbench.uut.spi.o_miso +@200 +- +@28 +testbench.uut.spi.o_active +@200 +- +@28 +testbench.uut.spi.in_bit[2:0] +@22 +testbench.uut.spi.data_in[7:0] +testbench.uut.spi.data_in_spi[7:0] +@200 +- +@28 +testbench.uut.spi.o_data_in_start +@29 +testbench.uut.spi.o_data_out_ready +@200 +- +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/rtl/state_filter.txt b/rtl/state_filter.txt new file mode 100644 index 0000000..7d9ddfa --- /dev/null +++ b/rtl/state_filter.txt @@ -0,0 +1,14 @@ +0 = halt +1 = status +2 = wbuf +3 = rbuf +4 = wmem0 +5 = wmem1 +6 = wmem2 +7 = wmem3 +8 = rmem0 +9 = rmem1 +10 = rmem2 +11 = rmem3 +12 = run0 +13 = run1 diff --git a/rtl/testbench.v b/rtl/testbench.v index def924b..72b5d7d 100644 --- a/rtl/testbench.v +++ b/rtl/testbench.v @@ -1,3 +1,4 @@ +`default_nettype none /* * Copyright (C) 2018 Clifford Wolf * @@ -17,6 +18,7 @@ module testbench; reg clock; + localparam spi_clock_period = 17; initial begin $dumpfile("testbench.vcd"); @@ -26,90 +28,85 @@ module testbench; forever #5 clock = ~clock; end - reg qpi_csb; - reg qpi_clk; + reg spi_csb; + reg spi_clk; - reg qpi_io0_reg; - reg qpi_io1_reg; - reg qpi_io2_reg; - reg qpi_io3_reg; + reg spi_mosi_reg = 0; + reg spi_miso_reg = 0; + reg xfer_read_start = 0; + reg xfer_wait_start = 0; - wire qpi_io0 = qpi_io0_reg; - wire qpi_io1 = qpi_io1_reg; - wire qpi_io2 = qpi_io2_reg; - wire qpi_io3 = qpi_io3_reg; + wire spi_mosi = spi_mosi_reg; + wire spi_miso = spi_miso_reg; - wire qpi_rdy; - wire qpi_err; + wire spi_rdy; + wire spi_err; mlaccel_top uut ( .clock (clock ), - .qpi_csb (qpi_csb), - .qpi_clk (qpi_clk), - .qpi_io0 (qpi_io0), - .qpi_io1 (qpi_io1), - .qpi_io2 (qpi_io2), - .qpi_io3 (qpi_io3), - .qpi_rdy (qpi_rdy), - .qpi_err (qpi_err) + .spi_csb (spi_csb), + .spi_clk (spi_clk), + .spi_miso (spi_miso), + .spi_mosi (spi_mosi) ); reg [7:0] xfer; task xfer_posedge; begin - if ($random & 15) begin - #17; - qpi_clk = 1; - end else begin - #17; - qpi_clk = 1; - #1; - qpi_clk = 0; - #1; - qpi_clk = 1; - end + #spi_clock_period; + spi_clk = 1; end endtask task xfer_negedge; begin - if ($random & 15) begin - #17; - qpi_clk = 0; - end else begin - #17; - qpi_clk = 0; - #1; - qpi_clk = 1; - #1; - qpi_clk = 0; - end + #spi_clock_period; + spi_clk = 0; end endtask task xfer_start; begin - #17; - qpi_csb = 0; + #spi_clock_period; + spi_csb = 0; end endtask task xfer_send; begin xfer_negedge; - qpi_io0_reg = xfer[4]; - qpi_io1_reg = xfer[5]; - qpi_io2_reg = xfer[6]; - qpi_io3_reg = xfer[7]; + spi_mosi_reg = xfer[7]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[6]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[5]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[4]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[3]; xfer_posedge; xfer_negedge; - qpi_io0_reg = xfer[0]; - qpi_io1_reg = xfer[1]; - qpi_io2_reg = xfer[2]; - qpi_io3_reg = xfer[3]; + spi_mosi_reg = xfer[2]; xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[1]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[0]; + xfer_posedge; + end endtask @@ -145,62 +142,92 @@ module testbench; end endtask + // null byte task xfer_wait; begin + + xfer_wait_start = 1; + xfer_negedge; + spi_miso_reg = 1'bz; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + xfer_negedge; - qpi_io0_reg = 1'bz; - qpi_io1_reg = 1'bz; - qpi_io2_reg = 1'bz; - qpi_io3_reg = 1'bz; xfer_posedge; xfer_negedge; xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_wait_start = 0; + end endtask task xfer_recv; begin + xfer_read_start = 1; + xfer_negedge; - qpi_io0_reg = 1'bz; - qpi_io1_reg = 1'bz; - qpi_io2_reg = 1'bz; - qpi_io3_reg = 1'bz; - xfer_posedge; + xfer_posedge; + xfer[7] = spi_miso; - xfer[4] = qpi_io0; - xfer[5] = qpi_io1; - xfer[6] = qpi_io2; - xfer[7] = qpi_io3; + xfer_read_start = 0; xfer_negedge; - xfer_posedge; + xfer_posedge; + xfer[6] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[5] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[4] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[3] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[2] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[1] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[0] = spi_miso; - xfer[0] = qpi_io0; - xfer[1] = qpi_io1; - xfer[2] = qpi_io2; - xfer[3] = qpi_io3; end endtask task xfer_stop; begin - if ($random & 3) begin - xfer_negedge; - end else begin - #17; - end + #spi_clock_period; - qpi_io0_reg = 1'bz; - qpi_io1_reg = 1'bz; - qpi_io2_reg = 1'bz; - qpi_io3_reg = 1'bz; xfer = 'bx; - #17; - qpi_csb = 1; - #17; - qpi_clk = 1; + #spi_clock_period; + spi_csb = 1; + #spi_clock_period; + spi_clk = 1; end endtask diff --git a/rtl/testbench_simple.v b/rtl/testbench_simple.v new file mode 100644 index 0000000..c434305 --- /dev/null +++ b/rtl/testbench_simple.v @@ -0,0 +1,328 @@ +`default_nettype none +/* + * Copyright (C) 2018 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module testbench; + reg clock; + localparam spi_clock_period = 17; + localparam no_glitch = 1; + localparam num_tests = 64; + + initial begin + $dumpfile("testbench.vcd"); + $dumpvars(0, testbench); + + #5 clock = 0; + forever #5 clock = ~clock; + end + + reg spi_csb; + reg spi_clk; + + reg spi_mosi_reg = 0; + reg spi_miso_reg = 0; + reg xfer_read_start = 0; + reg xfer_wait_start = 0; + + wire spi_mosi = spi_mosi_reg; + wire spi_miso = spi_miso_reg; + + wire spi_rdy; + wire spi_err; + + mlaccel_top uut ( + .clock (clock ), + .spi_csb (spi_csb), + .spi_clk (spi_clk), + .spi_miso (spi_miso), + .spi_mosi (spi_mosi) + ); + + reg [7:0] xfer; + + task xfer_posedge; + begin + if ($random & 15 || no_glitch) begin + #spi_clock_period; + spi_clk = 1; + end else begin + #spi_clock_period; + spi_clk = 1; + #1; + spi_clk = 0; + #1; + spi_clk = 1; + end + end + endtask + + task xfer_negedge; + begin + if ($random & 15 || no_glitch) begin + #spi_clock_period; + spi_clk = 0; + end else begin + #spi_clock_period; + spi_clk = 0; + #1; + spi_clk = 1; + #1; + spi_clk = 0; + end + end + endtask + + task xfer_start; + begin + #spi_clock_period; + spi_csb = 0; + end + endtask + + task xfer_send; + begin + xfer_negedge; + spi_mosi_reg = xfer[7]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[6]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[5]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[4]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[3]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[2]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[1]; + xfer_posedge; + + xfer_negedge; + spi_mosi_reg = xfer[0]; + xfer_posedge; + + end + endtask + + task xfer_send_byte; + input [7:0] data; + begin + xfer = data; + xfer_send; + end + endtask + + task xfer_send_hword; + input [15:0] data; + begin + xfer = data[7:0]; + xfer_send; + xfer = data[15:8]; + xfer_send; + end + endtask + + task xfer_send_word; + input [31:0] data; + begin + xfer = data[7:0]; + xfer_send; + xfer = data[15:8]; + xfer_send; + xfer = data[23:16]; + xfer_send; + xfer = data[31:24]; + xfer_send; + end + endtask + + // null byte + task xfer_wait; + begin + + xfer_wait_start = 1; + xfer_negedge; + spi_miso_reg = 1'bz; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_negedge; + xfer_posedge; + + xfer_wait_start = 0; + + end + endtask + + task xfer_recv; + begin + xfer_read_start = 1; + + xfer_negedge; + xfer_posedge; + xfer[7] = spi_miso; + + xfer_read_start = 0; + + xfer_negedge; + xfer_posedge; + xfer[6] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[5] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[4] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[3] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[2] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[1] = spi_miso; + + xfer_negedge; + xfer_posedge; + xfer[0] = spi_miso; + + end + endtask + + task xfer_stop; + begin + if ($random & 3 || no_glitch) begin + xfer_negedge; + end else begin + #spi_clock_period; + end + + xfer = 'bx; + + #spi_clock_period; + spi_csb = 1; + #spi_clock_period; + spi_clk = 1; + end + endtask + + integer cursor, len, i; + + initial begin + xfer_stop; + + #200; + + $display("sending bytes"); + $fflush; + + i= 0; + len = 1; + cursor = 0; + while (cursor < num_tests) begin + i = 0; + $display(" uploading %4d bytes from 0x%05x", len, cursor); + $fflush; + + xfer_start; + xfer_send_byte(8'h 21); + xfer_send_byte(cursor); + xfer_stop; + + xfer_start; + xfer_send_byte(8'h 23); + xfer_send_hword(cursor); + xfer_send_byte(len); + xfer_wait; + xfer_recv; + + while (xfer != 8'h 00) + xfer_recv; + xfer_stop; + + cursor = cursor + len; + end + $display("reading bytes"); + $fflush; + + len = 1; + cursor = 0; + while (cursor < num_tests) begin + $display(" downloading %4d bytes from 0x%05x", len, cursor); + $fflush; + + xfer_start; + xfer_send_byte(8'h 24); + xfer_send_hword(cursor); + xfer_send_byte(len); + xfer_wait; + xfer_recv; + while (xfer != 8'h 00) + xfer_recv; + xfer_stop; + + xfer_start; + xfer_send_byte(8'h 22); + xfer_wait; + xfer_recv; + if( xfer != cursor) begin + $display("ERROR at %4d: expected 0x%02x, got 0x%02x", cursor, cursor, xfer); + end + xfer_stop; + + cursor = cursor + len; + end + + + $finish; + end +endmodule diff --git a/rtl/top.v b/rtl/top.v index 4ee47e1..571bb4f 100644 --- a/rtl/top.v +++ b/rtl/top.v @@ -1,31 +1,13 @@ -/* - * Copyright (C) 2018 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - +`default_nettype none module mlaccel_top ( input clock, - input qpi_csb, - input qpi_clk, - inout qpi_io0, - inout qpi_io1, - inout qpi_io2, - inout qpi_io3, - output qpi_rdy, - output qpi_err + input spi_csb, + input spi_clk, + output spi_miso, + input spi_mosi, + output spi_rdy, + output spi_err ); integer i; @@ -89,73 +71,31 @@ module mlaccel_top ( reset <= !next_resetn; end + /********** QPI Interface **********/ - wire [3:0] qpi_io_oe; - wire [3:0] qpi_io_do; - wire [3:0] qpi_io_di; -`ifdef RADIANT - BB_B qpi_io_buf [3:0] ( - .B({qpi_io3, qpi_io2, qpi_io1, qpi_io0}), - .T_N(qpi_io_oe), - .I(qpi_io_do), - .O(qpi_io_di) - ); -`else - SB_IO #( - .PIN_TYPE(6'b 1010_01), - .PULLUP(1'b 0) - ) qpi_io_buf [3:0] ( - .PACKAGE_PIN({qpi_io3, qpi_io2, qpi_io1, qpi_io0}), - .OUTPUT_ENABLE(qpi_io_oe), - .D_OUT_0(qpi_io_do), - .D_IN_0(qpi_io_di) - ); -`endif - wire qpi_csb_di; - wire qpi_clk_di; -`ifdef RADIANT - assign qpi_csb_di = qpi_csb; - assign qpi_clk_di = qpi_clk; -`else - SB_IO #( - .PIN_TYPE(6'b 0000_01), - .PULLUP(1'b 1) - ) qpi_csb_buf ( - .PACKAGE_PIN(qpi_csb), - .D_IN_0(qpi_csb_di) - ); + wire spi_active; + assign spi_rdy = 1; + assign spi_err = 1; - SB_IO #( - .PIN_TYPE(6'b 0000_01), - .PULLUP(1'b 0) - ) qpi_clk_buf ( - .PACKAGE_PIN(qpi_clk), - .D_IN_0(qpi_clk_di) - ); -`endif - wire qpi_active; + spi_client spi ( + .i_clock (clock ), + .i_reset (reset ), + .o_active (spi_active), - mlaccel_qpi qpi ( - .clock (clock ), - .reset (reset ), - .active (qpi_active), - - .qpi_csb_di (qpi_csb_di), - .qpi_clk_di (qpi_clk_di), - .qpi_rdy_do (qpi_rdy ), - .qpi_err_do (qpi_err ), - .qpi_io_di (qpi_io_di ), - .qpi_io_do (qpi_io_do ), - .qpi_io_oe (qpi_io_oe ), - - .din_valid (din_valid ), - .din_start (din_start ), - .din_data (din_data ), - - .dout_valid (dout_valid), - .dout_ready (dout_ready), - .dout_data (dout_data ) + .i_spi_cs_n (spi_csb), + .i_spi_clk (spi_clk), + + .o_miso (spi_miso ), + .i_mosi (spi_mosi ), + + .o_data_in_valid (din_valid ), + .o_data_in_start (din_start ), + .o_data_in_data (din_data ), + + .i_data_out_valid (dout_valid), + .o_data_out_ready (dout_ready), + .i_data_out_data (dout_data ) ); /********** Cmd State Machine **********/ @@ -196,7 +136,7 @@ module mlaccel_top ( seq_start <= 0; seq_stop <= 0; - if (!qpi_active || din_start) begin + if (!spi_active || din_start) begin dout_valid <= 0; end @@ -512,173 +452,5 @@ module mlaccel_top ( .wdata (mem_wdata), .rdata (mem_rdata) ); -endmodule - -module mlaccel_qpi ( - input clock, - input reset, - output active, - - input qpi_csb_di, - input qpi_clk_di, - - output qpi_rdy_do, - output qpi_err_do, - - input [3:0] qpi_io_di, - output reg [3:0] qpi_io_do, - output reg [3:0] qpi_io_oe, - - output reg din_valid, - output reg din_start, - output reg [7:0] din_data, - - input dout_valid, - output dout_ready, - input [7:0] dout_data -); - assign qpi_rdy_do = 1; - assign qpi_err_do = 1; - - reg [3:0] di_data; - reg di_toggle; - reg di_start; - reg di_stx; - - reg [7:0] do_data; - reg [3:0] do_datax; - reg do_valid; - reg do_validx; - reg do_toggle; - - reg glitch_guard_clock_q0; - reg glitch_guard_di_toggle_q0; - reg glitch_guard_do_toggle_q0; - reg glitch_guard_di_stx_q0; - - reg glitch_guard_posedge; - reg glitch_guard_negedge; - reg glitch_guard_di_toggle; - reg glitch_guard_do_toggle; - reg glitch_guard_di_stx; - - always @(negedge clock) begin - glitch_guard_clock_q0 <= qpi_clk_di; - glitch_guard_di_toggle_q0 <= di_toggle; - glitch_guard_do_toggle_q0 <= do_toggle; - glitch_guard_di_stx_q0 <= di_stx; - end - - always @(posedge clock) begin - // protect against clock glitching: logic level of clock - // must have been low before posedge and high before negedge - glitch_guard_posedge <= !glitch_guard_clock_q0; - glitch_guard_negedge <= glitch_guard_clock_q0; - - // delay some signals to protect against double clocking - glitch_guard_di_toggle <= glitch_guard_di_toggle_q0; - glitch_guard_do_toggle <= glitch_guard_do_toggle_q0; - glitch_guard_di_stx <= glitch_guard_di_stx_q0; - end - - always @(posedge qpi_clk_di, posedge qpi_csb_di) begin - if (qpi_csb_di) begin - di_data <= 0; - di_toggle <= 1; - di_start <= 1; - di_stx <= 1; - end else begin - if (glitch_guard_posedge) begin - di_data <= qpi_io_di; - di_toggle <= !glitch_guard_di_toggle; - if (glitch_guard_di_toggle) - di_stx <= 0; - if (glitch_guard_di_toggle && !glitch_guard_di_stx) - di_start <= 0; - end - end - end - - always @(negedge qpi_clk_di, posedge qpi_csb_di) begin - if (qpi_csb_di) begin - qpi_io_oe <= 0; - qpi_io_do <= 0; - do_toggle <= 0; - do_validx <= 0; - do_datax <= 0; - end else begin - if (glitch_guard_negedge) begin - if (di_start) - do_toggle <= 0; - else - do_toggle <= !glitch_guard_do_toggle; - - if (glitch_guard_do_toggle) begin - qpi_io_oe <= {4{do_valid}}; - qpi_io_do <= do_data[7:4]; - end else begin - qpi_io_oe <= {4{do_validx}}; - qpi_io_do <= do_datax; - end - - do_validx <= do_valid; - do_datax <= do_data; - end - end - end - - reg clk_q0, clk_q1, clk_q2; - reg do_toggle_q0, do_toggle_q1; - reg active_q0, active_q1; - - always @(negedge clock) begin - clk_q0 <= qpi_clk_di; - do_toggle_q0 <= do_toggle; - active_q0 <= !qpi_csb_di; - end - - always @(posedge clock) begin - clk_q1 <= clk_q0; - clk_q2 <= clk_q1; - do_toggle_q1 <= do_toggle_q0; - active_q1 <= active_q0; - end - reg dout_busy; - assign dout_ready = do_toggle_q1 && dout_valid && !dout_busy; - assign active = active_q1; - - always @(posedge clock) begin - din_valid <= 0; - if (clk_q1 && !clk_q2) begin - if (!di_toggle) begin - din_data[7:4] <= di_data; - end else begin - din_valid <= 1; - din_start <= di_start; - din_data[3:0] <= di_data; - end - end - if (dout_valid && dout_ready) begin - do_valid <= 1; - do_data <= dout_data; - dout_busy <= 1; - end - if (!do_toggle_q1) begin - dout_busy <= 0; - end - if (!active) begin - do_valid <= 0; - do_data <= 0; - dout_busy <= 0; - end - if (reset) begin - do_valid <= 0; - do_data <= 0; - din_valid <= 0; - din_start <= 0; - din_data <= 0; - dout_busy <= 0; - end - end endmodule