-
Running on Off-the-Shelf Card(s)
08/06/2021 at 12:22 • 0 commentsAlso, got the code running on the the QMTECH EP4CE15 FPGA "Starter Kit". Details here.
Specifications
- On-Board FPGA: EP4CE15F23C8N;
- On-Board FPGA external crystal frequency: 50MHz;
- EP4CE15F has rich RAM resource;
- EP4CE15F has 15K logic cells;
- On-Board Winbond SPI Flash W25Q64, 8M bytes for user configuration code;
- On-Board 32MB Winbond SDRAM, W9825G6KH-6;
- On-Board 3.3V power supply for FPGA by using MP2315 wide input range DC/DC;
- Cyclone IV Starter Kit provides camera interface, 2xPMOD headers and 40P Male header for User IOs;
- Cyclone IV Starter Kit has 2 user switches;
- Cyclone IV Starter Kit has 2 user LEDs;
- Cyclone IV Starter Kit has JTAG interface, by using 10p, 2.54mm pitch header;
- Cyclone IV Starter Kit provides GMII Ethernet by using RealTek RTL8211EG;
- Cyclone IV Starter Kit provides 7-SEG LEDs;
- Cyclone IV Starter Kit provides USB to UART serial port by using CP2102-GMR;
- Cyclone IV Starter Kit provides VGA 5-6-5 interface by using resistor dividers;
- Cyclone IV Starter Kit PCB size is: 9.96cm x 9.96cm;
- Default power source for board is: 1A@5V DC, the DC header type: DC-050, 5.5mmx2.1mm;
-
Put into Enclosure
08/06/2021 at 11:55 • 0 comments -
Serial startup message
02/12/2021 at 10:48 • 0 commentsHere's the serial output:
Conducting sanity check... Firmware received - launching Heap_low: cef0, heap_size: 1ff2110 Mouse timed out Initialising SD card SPIspin Done - waiting Done SPIspin Done - waiting Done cmd_CMD8 response: 1 CMD8_1 response: 0 CMD8_2 response: 0 CMD8_3 response: 1 CMD8_4 response: aa SPIspin Done - waiting Done CMD55 1 CMD41 1 SPIspin Done - waiting Done CMD55 1 CMD41 0 CMD58 0 CMD58_2 c0 SDHC card detectedSwapping byte order of partition entries Start: 8192 PartitionCount: 1 Partition: 0 Start: 8192 Size: 62325760 Read boot sector from first partition FindDrive() returnedC024576) Changed directory Dhrystone Benchmark, Version 2.1 (Language: C) Program compiled without 'register' attribute Execution starts, 25000 runs through Dhrystone Execution ends Final values of the variables used in the benchmark: Int_Glob: 5 should be: 5 Bool_Glob: 1 should be: 1 Ch_1_Glob: A should be: A Ch_2_Glob: B should be: B Arr_1_Glob[8]: 7 should be: 7 Arr_2_Glob[8][7]: 25010 should be: Number_Of_Runs + 10Ptr_Glob-> Ptr_Comp: 35210 should be: (implementation-dependent) Discr: 0 should be: 0 Enum_Comp: 2 should be: 2 Int_Comp: 17 should be: 17 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGNext_Ptr_Glob-> Ptr_Comp: 35210 should be: (implementation-dependent), same as above Discr: 0 should be: 0 Enum_Comp: 1 should be: 1 Int_Comp: 18 should be: 18 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGInt_1_Loc: 5 should be: 5 Int_2_Loc: 13 should be: 13 Int_3_Loc: 7 should be: 7 Enum_Loc: 1 should be: 1 Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING should be: DHRYSTONE PROGRAM, 1'ST STRINGStr_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING should be: DHRYSTONE PROGRAM, 2'ND STRING User time: 2920 Microseconds for one run through Dhrystone: 116 Dhrystones per Second: 8561 VAX MIPS rating * 1000 = 4871
32 MB of allocated memory (33,497,360 bytes)
-
Demo Video #1
02/06/2021 at 11:24 • 0 comments -
Passing Variables from C to Assembly under GCC
01/23/2021 at 13:21 • 0 commentsI've loved the (on-line GodBolt) Compiler Explorer project for a while now. It lets you type code in one window and see it compiled to assembly language in another window. There's a Compiler Explorer site which does 68k cross compiling. This also lets you play with compiler options like optimization.
GodBolt Compiler Explorer GCC versions
The GodBolt tool supports various GCC versions.
My GCC compiler toolchain uses version:
I tried various GCC versions and the results in the below simple case were the same.
Passing variables from C to assembly functions
One of the more painful things to grapple with is passing variables from C to assembly language. To understand the passing process, let's look at a simple example. Here's C code which passes two variables to an add function and returns the sum of the two numbers:
// test passing variables using GCC on the 68K CPU int addTwoNums(int a,int b) { return (a+b); } main(void) { int i =- 2; int j = 3; addTwoNums(i,j); }
Here's where the GodBolt Compiler Explorer comes in handy. Let's look at how the GCC compiler handles passing variables between C functions to see what we'd need to do if we write assembly that gets called from C.
__Z10addTwoNumsii: link.w a5,#0 move.l (8,a5),d0 add.l (12,a5),d0 unlk a5 rts _main: link.w a5,#-8 moveq #-2,d0 move.l d0,(-4,a5) moveq #3,d0 move.l d0,(-8,a5) move.l (-8,a5),-(sp) move.l (-4,a5),-(sp) jbsr __Z10addTwoNumsii addq.l #8,sp moveq #0,d0 unlk a5 rts
Values which are passed from the C function to the assembly language routine relative to the stack. In this example, the first variable, i, is passed at an offset of -4 from the a5 register. The second variable is passed at an offset of -8 from the a5 register.
The return value from the add function is found in d0.
The routine is bounded by the link at the start and unlk *unlink" at the end of the routines. These are described in this 68000 Programmers Reference document.
If we want to write assembly language routines that can be called from C we can mimic this functionality. But there's a rub with the AMR code that adds a tiny bit of complexity (or is it simplification?).
AMR's C/Assembly Code
Let's take a look at one of the AMR pieces of assembly code to see what was done for that code. This code (spi_readsector.s) reads a sector from the SD card and loads it to an address range specified by register a0:
SPI_PUMP equ $81000100 XDEF spi_readsector spi_readsector move.l 4(a7),a0 movem.l d2-d7/a2,-(a7) moveq #15,d7 lea SPI_PUMP,a1 move.w (a1),d0 .loop movem.l (a1),d0-d6/a2 movem.l d0-d6/a2,(a0) add.l #32,a0 dbf d7,.loop movem.l (a7)+,d2-d7/a2 rts
The code pushes the registers used by the routine at the start onto the stack and restores (via pull) the registers before the return from subroutine. This preserves the registers in the calling routine.
Take note, though. This code isn't using the link and unlink. It's not using the a5 register as the stack frame for the routine. The reason that the code can do this is found in the gcc options found in the makefile. The option used is: -fomit-frame-pointer. This causes the compiler to not use the frame pointer. Instead it uses the a7 stack pointer directly. Obviously this is more efficient both in speed and memory usage.
That's also why the assembly language routine looks for the first passed variable at 4 from the a7 register instead of 8 in the GCC example. Adding the -fomit-frame-pointer option to the Godbolt compiler produces the following assembly code:
__Z10addTwoNumsii: move.l (4,sp),d0 add.l (8,sp),d0 rts _main: subq.l #8,sp moveq #-2,d0 move.l d0,(4,sp) moveq #3,d0 move.l d0,(sp) move.l (sp),-(sp) move.l (8,sp),-(sp) jbsr __Z10addTwoNumsii addq.l #8,sp moveq #0,d0 addq.l #8,sp rts
This code has the same form as AMR's code. The first line in _main reserves 2 longs (8 bytes) for the stacked variables used by the routine.
Compiler Options
-fomit-frame-pointer option instructs the compiler to not store stack frame pointers if the function does not need it. You can use this option to reduce the code image size.
-fno-common specifies that the compiler places uninitialized global variables in the BSS section of the object file. This inhibits the merging of tentative definitions by the linker so you get a multiple-definition error if the same variable is accidentally defined in more than one compilation unit.
-
Fixed Display RAM Accesses
01/17/2021 at 18:27 • 0 commentsThe rectangles code wasn't working correctly on the EP4 FPGA card. Luckily, I found the problem relatively easily. Required setting the rows and columns for the SDRAM part that is used on the card. In the C4BoardTopLevel file.
tg68tst : entity work.VirtualToplevel generic map ( -- W9825C6KH-6 Winbond 4M X 4 Banks x 16 bits SDRAM -- 13 rows, 9 columns sdram_rows => 13, sdram_cols => 9,
The same fix needs to be done for the Cyclone V card since it used the same SDRAM part.
-
Bootloader and SD Card
01/16/2021 at 14:08 • 0 commentsBoot Process
The code has a bootloader which loads the executable program from the SD card. The bootloader code runs from ROM on the FPGA.
SD Card Image
The SD Card contains a single file, boot.sre . This file is run automatically when the card is powered on.
The image is an S record. The SD card is a FAT32 formatted card.
-
GitHub under VirtualBox
01/16/2021 at 13:05 • 0 commentsSync up with repository
git pull
Move changes to GitHub
git add .
git commit 'stuff'
git push
-
Build on EP4CE15
01/16/2021 at 11:38 • 0 commentsUses a bit more resources on an EP4CE15 card: