Git Product home page Git Product logo

arrowzip's Introduction

The Zip CPU

The Zip CPU is a small, light-weight, RISC CPU. Specific design goals include:

  • 32-bit. All registers, addresses, and instructions are 32-bits in length.

  • A RISC CPU. Instructions nominally complete in one cycle each, with exceptions for multiplies, divides, memory accesses, and (eventually) floating point instructions.

    (Note that the ZipCPU is not a RISC-V CPU, nor does it copy from any other instruction set but its own.)

  • A load/store architecture. Only load and store instructions may access memory.

  • Includes Wishbone, AXI4-Lite, and AXI4 memory options.

  • A (minimally) Von-Neumann architecture

    The Wishbone wrappers share buses for instructions and data, the AXI4-Lite and AXI4 wrappers have separate bus interfaces for each. The address space itself, however, needs to be common.

  • A pipelined architecture, having stages for prefetch, decode, read-operand(s), a combined stage containing the ALU, memory, divide, and floating point units, and then the final write-back stage.

  • A two mode machine: supervisor and user, with each mode having a different access level.

  • Completely open source, licensed under the GPLv3.

Unique features and characteristics

  • Only 29 instructions are currently implemented. Six additional instructions have been reserved for a floating point unit, but such a unit has yet to be implemented.

  • (Almost) all instructions can be executed conditionally. Exceptions include load immediate (LDI), the debug break instruction (BREAK), the bus lock (LOCK) and simulation instructions (SIM), and the no-operation instruction (NOOP). The assembler will quietly turn a conditional load immediate into a two-instruction equivalent (BREV, LDILO).

  • The CPU makes heavy use of pipelining wherever and whenever it can. Hence, when using a pipelined memory core, loading two vaues in a row may cost only one clock more than just loading the one value.

  • The CPU has no interrupt vectors, but rather two register sets. On any interrupt, the CPU just switches from the user register set to the supervisor register set. This simplifies interrupt handling, since the CPU automatically saves, preserves, and restores the supervisor's context between enabling interrupts and receiving the next interrupt. An optional interrupt peripheral may be used to combine multiple external interrupts into a single interrupt line.

Getting Started

If you'd like to get started with the ZipCPU, you might wish to know that this repository contains the CPU, its documentation, and the toolchain. The CPU implementation found here, though, is just that: a CPU. This implementation requires a bus with peripherals hanging off of it, things such as RAM, flash (ROM), serial port, etc. This is just where I keep the CPU apart from any necessary peripherals.

So, if you want to try out the CPU, feel free to download and build this repository (use git-clone with a depth of 1--there's a lot of stuff in the git repo that you don't necessarily need). You'll need it for the binutils, GCC, and newlib support provided by it.

Once you've built these tools, then I'd suggest you look into the ZBasic repository. That repository places the CPU in an environment with block RAM, QSPI flash, and SD-card (SPI protocol) access. From that repository, you can either tweak the distro (main.v, regdefs.h, board.h, board.ld) to add the peripherals you want to use the CPU with, or you can use AutoFPGA to adjust your RAM size, add or remove peripherals and so forth while maintaining (creating, really) all of these files for you.

The sim/ subdirectory also contains a version of the ZipCPU in a usable environment for simulation purposes. This includes the CPU, possibly more CPU's for a multiprocessor environment, bus interconnect, memory, a simulated serial port, and a couple more peripherals.

If you aren't interested in simulating the CPU, there is an assembly level debugger that you can use to stop and step the CPU, as well as an integrated wishbone scope that you can use to get traces from within the design while it is running.

Need help?

If you'd like to use the ZipCPU, and don't know where to begin, feel free to find me on IRC as ZipCPU. I've created a #zipcpu channel on several IRC servers that I tend to inhabit. If you get stuck, feel free to drop by and ask for help. You can also drop by just to say hi. Either way, please introduce yourself and give me some time to respond.

Current Status

You can also read about the ZipCPU via several blog articles posted at zipcpu.com! Articles you might find valuable include:

Not yet integrated

  • The MMU that was written for the ZipCPU now needs to be rewritten in order to work in the new ZipCore context. My plan is to place the MMU between the ZipCore and the various bus aware wrappers, providing a similar interface to the one offered by the ZipCore. That way, caches will be based on physical addressing--solving one of the bigger problems I had when using the MMU.

  • FATFS support now exists for the SDCard, it's just not (yet) integrated into the newlib C-library.

  • The ZipOS would greatly speed up and improve the bare bones newlib library--primarily by providing "O/S" level interrupt support when using the library. This integration has not (yet) been accomplished.

    On the other hand, if the MMU is available, I might rather just create a Linux distribution.

Commercial Opportunities

The GPLv3 license should be sufficient for most (all) academic and hobby purposes, and certainly for all simulation based purposes. If you find, however, that the GPLv3 license is insufficient for your needs, other licenses can be purchased from Gisselquist Technology, LLC.

This applies to all but the toolchain, for which GPLv3 should work for all purposes. (Besides, I don't own the licenses for Binutils, GCC, or newlib.)

arrowzip's People

Contributors

zipcpu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

arrowzip's Issues

RTC working ?

Hi Dan

Just a short question: Is it possible that the rtclight module is not really working?

I do have the regs CLOCK, ALARM, TIMER, STOPWATCH, but none of them counts in any case. I can set the regs, but they don't seem to change at all.

But maybe I am missing something...

hello.c

I'm having problems to get any output from the test program "hello".

$ ./wbregs version; ./wbregs buildtime
00800014 ( VERSION) : [....] 20190308
00800000 (BUILDTIME) : [....] 00081204

When I start zipload 'hello' the first time, I get an error:

 time ./zipload -v -r ../board/hello
ZipLoad: Verbose mode on
Halting the CPU
Loading: ../board/hello
Sending to flash: 01000000-01000134
Sending to flash: 01000134-01004a54
ERASING SECTOR: 01000000
Erasing sector: 000000
SECTOR ERASE FAILED!
ERR: Could not write program to flash

real    1m18.194s
user    0m0.323s
sys     0m1.361s

This seems to be the flash erase.

Starting a second time, no flash erase is done. Instead the code is written:

$ time ./zipload -v -r ../board/hello                                                            ZipLoad: Verbose mode on
Halting the CPU
Loading: ../board/hello
Sending to flash: 01000000-01000134
Sending to flash: 01000134-01004a54
Writing page: 0x01000000 - 0x010000ff
Writing page: 0x01000100 - 0x010001ff
Writing page: 0x01000200 - 0x010002ff
Writing page: 0x01000300 - 0x010003ff
[...]
Writing page: 0x01004900 - 0x010049ff
Writing page: 0x01004a00 - 0x01004aff
Clearing the CPUs registers
Setting PC to 01000000
Starting the CPU
CPU Status is: 0000000f

real    8m22.885s
user    1m45.880s
sys     4m4.044s

After taking this 8,5 min, there is no output visible, neither on telnet session, nor on the netuart console.

If I read the code correctly (which is rather small), it should output "Hello, world!".

[Enforcement] Variable defined before used in hbconsole.v.

According to the Verilog LRM (IEEE Std 1800โ„ข-2012) Section 6.5, all variables must be declared before they are used, apart from implicit nets. Without the `default_nettype set to none, the variable ps_full could be inferred as a local net by different synthesis tools.

This line uses ps_full before is declared.
Lines 156 to 170 of hbconsole.v can be moved above this declaration to accomplish the design intent.

Where to continue?

Hi Dan

So, I have the design running on the MAX1000 now. I am, however, not sure if it works correctly, as I don't know the whole thing at all. Here are my observations so far:

  • board consumes 134mA
  • LEDs are running knightrider
  • wbregs works when reading, but not when writing, it seems:
 $./wbregs BUILDTIME
00400000 (BUILDTIME) : [.!5(] 00213528
 $./wbregs VERSION
00400014 ( VERSION) : [....] 20190219
$ ./wbregs TIMER
00500044 (   TIMER) : [....] 00000000
$ ./wbregs TIMER 0x12345678
00500044 (   TIMER)-> 12345678
$ ./wbregs TIMER
00500044 (   TIMER) : [....] 00000000
$ ./wbregs FLASH
00800000 (   FLASH) : [....] 00000000
$ ./wbregs RAM
00600000 (     RAM) : [....] 00000000
$ ./wbregs ALARM
0050004c (   ALARM) : [....] 00000000
$ ./wbregs BUSTIMER
00500000 (BUSTIMER) : [....] 00000000
$ ./wbregs BUSTIMER 0x01
00500000 (BUSTIMER)-> 00000001
$ ./wbregs BUSTIMER
00500000 (BUSTIMER) : [....] 00000000
  • zipload complains about wrong board
$ ./zipload ../board/cputest
Could not communicate with board (invalid version)
  • zipdbg shows buserror:
Peripherals                   CPU State: 0x00000613 Supervisor mode
>PIC > 0x00000000<   WDT : 0x00000000    WBUS: 0x00000000    PIC2: 0x00000000
 TMRA: 0x00000000    TMRB: 0x00000000    TMRC: 0x00000000    JIF : 0x00000000
 MTSK: 0x00000000    MOST: 0x00000000    MPST: 0x00000000    MICT: 0x00000000

Supervisor Registers
 sR0 : 0x00000000    sR1 : 0x00000000    sR2 : 0x00000000    sR3 : 0x00000000 
 sR4 : 0x00000000    sR5 : 0x00000000    sR6 : 0x00000000    sR7 : 0x00000000 
 sR8 : 0x00000000    sR9 : 0x00000000    sR10: 0x00000000    sR11: 0x00000000 
 sR12: 0x00000000    sSP : 0x00000000    sCC :           Z   sPC : 0x0060000c 
User Registers
 uR0 : 0x00000000    uR1 : 0x00000000    uR2 : 0x00000000    uR3 : 0x00000000
 uR4 : 0x00000000    uR5 : 0x00000000    uR6 : 0x00000000    uR7 : 0x00000000
 uR8 : 0x00000000    uR9 : 0x00000000    uR10: 0x00000000    uR11: 0x00000000
 uR12: 0x00000000    uSP : 0x00000000    uCC :               uPC : 0x00000000


                                                     >00000000 (Bus Err)
 0x00600014 0x00000000  SUB        $0,R0              00000004 (Bus Err)
 0x00600010 0x00000000  SUB        $0,R0              00000008 (Bus Err)
>0x0060000c 0x00000000  SUB        $0,R0              0000000c (Bus Err)
 0x00600008 0x00000000  SUB        $0,R0              00000010 (Bus Err)

Any idea, how best to go forward? I still don't know this well enough...

dumpflash not working

Before this test I had run "hello", so that the flash got successfully written to.

 ./wbregs version
00600014 ( VERSION) : [....] 20190309
$ ./wbregs buildtime
00600000 (BUILDTIME) : [..GC] 00114743
$ time ./dumpflash 
Before starting, nread = 0
VERSION: 20190309

READ-COMPLETE
The read was accomplished in 19 bytes over the UART

real    0m0.019s
user    0m0.000s
sys     0m0.013s

The file is 8MB large, but contains only zeros.

Error (12006): Node instance "dspi_ddr_csn" instantiates undefined entity "altoddr".

I am still very new to FPGAs and your AutoMake powered designs in special. So, please bear with me.

When I try to import this design into quartus, I get the following errors on design analysis:

Error (12006): Node instance "dspi_ddr_csn" instantiates undefined entity "altoddr". Ensure that required library paths are specified correctly, define the specified entity, or change the instantiation. If this entity represents Intel FPGA or third-party IP, generate the synthesis files for the IP.
Error (12006): Node instance "dspi_ddr_sck" instantiates undefined entity "altoddr". Ensure that required library paths are specified correctly, define the specified entity, or change the instantiation. If this entity represents Intel FPGA or third-party IP, generate the synthesis files for the IP.
Error (12006): Node instance "dspi_d0" instantiates undefined entity "addrio". Ensure that required library paths are specified correctly, define the specified entity, or change the instantiation. If this entity represents Intel FPGA or third-party IP, generate the synthesis files for the IP.
Error (12006): Node instance "dspi_d1" instantiates undefined entity "addrio". Ensure that required library paths are specified correctly, define the specified entity, or change the instantiation. If this entity represents Intel FPGA or third-party IP, generate the synthesis files for the IP.

This seems to emenate from the toplevel.v file, where there are the following instatiations:

	// Wires for setting up the QSPI flash wishbone peripheral
	//
	//
	// QSPI)BMOD, Dual SPI bus mode, Bus modes are:
	//	0?	Normal serial mode, one bit in one bit out
	//	10	Dual SPI mode, going out
	//	11	Dual SPI mode coming from the device (read mode)
	altoddr dspi_ddr_csn(
		.outclock(s_clk),
		.din({(2){ w_dspi_cs_n}}),
		.pad_out(o_dspi_cs_n));
	altoddr dspi_ddr_sck( .outclock(s_clk),
		// .din({ !w_dspi_sck, 1'b1 }),
		.din({(2){w_dspi_sck}}),
		.pad_out(o_dspi_sck));
	addrio	dspi_d0(.inclock(s_clk), .outclock(s_clk),
			.dout({dspi_datp[0], dspi_datn[0]}),
			.din({(2){o_dspi_dat[0]}}),
			.pad_io(io_dspi_dat[0]),
			.oe(!dspi_bmod[0]));
	addrio	dspi_d1(.inclock(s_clk), .outclock(s_clk),
			.dout({dspi_datp[1], dspi_datn[1]}),
			.din({(2){o_dspi_dat[1]}}),
			.pad_io(io_dspi_dat[1]),
			.oe((dspi_bmod == 2'b10)?1'b1:1'b0));

What am I missing here? Where do I find these modules?

Thanks!

Support for CYC1000

The CYC1000 (https://www.arrow.com/en/products/cyc1000/arrow-development-tools) is a sister board of the MAX1000. It is very similar, in size as well as the components used. The main difference is the FPGA. Instead of a MAX FPGA it is a 10CL025YU256C8G. This differs in so far as it is a.) much bigger (24kLE compared to the 8kLE of the MAX10, and twice the amount of RAM), b.) uses external flash to store its configuration and 3.) doesn't support analog inputs.

Interestingly, it is very easy to compile and run the arrowzip on that board with only minimal changes:

Fitter Status	Successful - Thu Mar 14 11:05:45 2019
Quartus Prime Version	18.1.0 Build 625 09/12/2018 SJ Lite Edition
Revision Name	CYC1000Zip
Top-level Entity Name	toplevel
Family	Cyclone 10 LP
Device	10CL025YU256C8G
Timing Models	Final
Total logic elements	5,568 / 24,624 ( 23 % )
Total registers	3025
Total pins	54 / 151 ( 36 % )
Total virtual pins	0
Total memory bits	265,216 / 608,256 ( 44 % )
Embedded Multiplier 9-bit elements	16 / 132 ( 12 % )
Total PLLs	1 / 4 ( 25 % )

All test programs (cputest, memtest and hello) all work perfectly fine!
The changes needed to get this working are very little:

  • new pin definition file (qsf)
  • exchange of the yaddro and yaddrio functions

There are still some small issues to be tackled:

  1. The SPI flash is only 2MB big. The first MB is used to store the FPGA config and should not be accessible.
  2. The FPGA has twice as much RAM, which could be used.

Can you direct me how best to change these settings? I guess they are somewhere in auto-data, right?

And how would you think it makes most sense to manage this revision? Adding a new branch within git or better a revision within Quartus?

Flash erase not recognizing finished erase

Hi Dan

As you already mentioned, there is an issue with the flash controller not recognizing the finished erase cycle. I thought I could make sense to follow that issue with a separate issue. So, here is the info:

$ ./wbregs version
00600014 ( VERSION) : [....] 20190309
$ ./wbregs buildtime
00600000 (BUILDTIME) : [..GC] 00114743
$ ./zipload -v -r ../board/hello
ZipLoad: Verbose mode on
Halting the CPU
Loading: ../board/hello
Sending to flash: 01000000-01000134
Sending to flash: 01000134-01004a54
ERASING SECTOR: 01000000
Erasing sector: 000000

** [not finishing at all even after 20 min]**

$ ./zipload -v -r ../board/hello
ZipLoad: Verbose mode on
Halting the CPU
Loading: ../board/hello
Sending to flash: 01000000-01000134
Sending to flash: 01000134-01004a54
Writing page: 0x01000000 - 0x010000ff
Writing page: 0x01000100 - 0x010001ff
[...]
Writing page: 0x01004900 - 0x010049ff
Writing page: 0x01004a00 - 0x01004aff
Clearing the CPUs registers
Setting PC to 01000000
Starting the CPU
CPU Status is: 0000000f

A second start then recognizes that the flash is erased and starts writing.

Great article

Hi Dan

I read your article (http://zipcpu.com/zipcpu/2019/03/12/arrowzip.html). It is really very well written and contains lots of useful information. Thanks for publishing that!

I have a couple of remarks from my side as a beginner/user here:

Missing files in repo:

Great that you could get rid of the altera_gpio_lite file. Still, the repo is having some small changes needed in order to make it usable as is: 1.) it needs the pin definition file (qsf) 2.) "port.h" still has as a default the "jericho" hostname instead of "localhost" and 3) "sw/board/Makefile" is referring to "/home/dan/work/..." (I replaced that with a relative path; not sure though if that would be the best approach)
I can send you a small patch that adds the missing files and fixes the "jericho". These are really minor changes (the last 0.01%), but could help newbies like me.

Interface and Flash speed:

I completely agree. That is a major issue. If you really want to write programs that run on the arrowzip, then you can't always wait for 10 min to flash a simple "Hello World". I have no idea, howto fix this. Maybe a mixture of a faster interface (using compression?) and flashing locally via small helper program on zipcpu.
A faster communication would also help with zipdbg. Currently it takes about 5 seconds to move the cursor. So, for real on device debugging, it is rather useless. What do you think?

"Missing" functionality, e.g. accelerator

While I also think that the accelerator is not really needed, it would be fun to have. Additionally, there are also ADCs on the board that can read from several analog input pins (and even with the possibility to read the temperature of the board). And let's not forget there are of course many digital I/Os, which would be nice to be able to use. So, on top of the accelerator module, a module for GPIO usage and one for analog inputs would be great.

Size of the Soc on the FPGA:

While I agree that 5700 is not really "slim", I do think it doesn't matter. I believe that, instead, everything should be included that makes sense on the board, even if it goes up to 100% usage. Why? Because due to your great AutoFPGA, it should easily be possible for the user to comment out blocks such as the RTC etc, if the user needs more free space on the FPGA. Adding stuff is always more difficult than removing. So, I'd love to see a faster communication module, GPIO, ADC and accelerator support included, with the possibility to easily comment them out of the Makefile, if not needed.

As mentioned, these are just small suggestions. Your arrowzip is a great piece of work. I am sure many users of the MAX1000 will try it out.

great project

I also got this board to learn about FPGA. It would be too great to also have the ZipCPU on this board.
But it looks very daunting to me. Do you think you can get it working?

Cheers

Michael

output of memtest

If I read the memtest prog correctly, it should turn on 5 of the 8 LEDs, right?
Well, after starting, the program just turns on all 8 LEDs. No output on telnet or netuart, which is to be expected, right?

$ time ./zipload -v -r ../board/memtest
ZipLoad: Verbose mode on
Halting the CPU
Loading: ../board/memtest
Writing to MEM: 00c00000-00c0039c
Clearing the CPUs registers
Setting PC to 00c00000
Starting the CPU
CPU Status is: 0000200f

real    0m4.846s
user    0m1.380s
sys     0m3.431s

Loading is pretty fast.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.