Giter Site home page Giter Site logo

sy2002 / qnice-fpga Goto Github PK

View Code? Open in Web Editor NEW
69.0 69.0 15.0 32.73 MB

QNICE-FPGA is a 16-bit computer system for recreational programming built as a fully-fledged System-on-a-Chip in portable VHDL.

Home Page: http://qnice-fpga.com

License: Other

VHDL 38.96% Assembly 43.01% C 15.69% Shell 0.59% Ruby 0.06% Perl 0.18% CSS 0.03% HTML 0.36% Python 0.14% Vim Script 0.09% Tcl 0.90%
16-bit assembler c cpu fpga fpga-game fpga-tutorial learn-fpga open-hardware qnice sd-card soft-core system-on-chip tutorial vga vhdl vhdl-examples vhdl-tutorial

qnice-fpga's People

Contributors

bernd-ulmann avatar mjoergen avatar sy2002 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar

qnice-fpga's Issues

CPU R14 (status register): Mismatch between hardware and emulator

The instruction

MOVE 0x00FF, R14

works differently on the emulator and the hardware.

On the emulator, all flags (in particular the overflow flag V) are set.

On the hardware, the overflow flag is not set.

In the file qnice_cpu.vhd in lines 580-587 I see the comment:

-- not all parts of the SR are writeable: only the upper 8 bit plus
-- the M, C and X register are writeable, 

So what is the 'correct' behaviour? And what is the 'M' flag ? I don't see it mentioned anywhere in the QNICE introduction document.

Sift through TODO.txt and check for interessting stuff

@MJoergen I personally would be excited a lot about the VGA topic. But just in case: Here in TODO.txt are some more topics that you might want to have a look at for V1.7. In case you find something that you want to do: Just make an issue and assign it to yourself. In that case, please delete the item from TODO.txt as we try not to have redundancy between the issues list in GitHub and the TODO.txt. The latter one is more like a longterm "backlog"...

Please close this issue when you're done (independent from if you found anything in TODO.txt or not)

P.S. Of course feel free to add your own ideas to TODO.txt (longterm backlog) as well as to the GitHub issues.

Make the native assembler independent from an external preprocessor

This one is not urgent as the use case would also need writeable SD cards, FAT32 to support writing and possibly also support for more RAM:

The idea is: One day to be able to develop for QNICE on the QNICE. For example do write and assemble QNICE assembler while working on QNICE hardware.

Besides the fact that for that we also would need a nice assembler text editor on QNICE (or even an QNICE assmbler IDE ๐Ÿ˜ ): We need the assembler to run on QNICE.

And for that we need to make it "stand-alone", i.e. independent from an external C preprocessor.

Second timer (aka timer1) does not seem to work in the emulator

How to reproduce:

  • Experiment 1: run test_programs/timer_test.asm (which works on the hardware) on the emulator: Neither timer0 nor timer1 will start

  • Experiment 2: comment out the invokation of timer1 (by not having any ISR written) and rename the timer0 registers to timer1 => timer1 will not start

Refactor mmio_mux

@MJoergen let's use this issue to get the refactored and much more elegant mmio_mux working.

Originally, there was pull request #16, but this lead to very strange behaviours of the keyboard. So I reverted the PR back to the old design. Here is the problem description that can also be found in PR #16:

Problem description

I merged the PR, synthesized with Vivado and then run into a strange effect, when performing some additional tests on my loccal Nexys4DDR hardware.

Let's start first with what works fine:

  • You already tested eae.asm, cpu_test.asm and ise.asm: I retested: Works.
  • To check if the VGA registers and the SD card registers and the PS2/USB keyboard stills work, I loaded Q-TRIS from qbin/q-tris.out from the SD card and played it: Works only partially: The keyboard behaves very strange: see description below (But VGA and SD card seem to work fine)
  • To test if the TIL leds still work, I ran regbank.asm: Works.
  • To check the UART, I switched STDIN/OUT and connected by a serial program and I used qtransfer: Works.

PS2/USB Keyboard does not work reliably any more:

Here is the strange effect I observe on the PS2/USB keyboard: Many times, I need to hit keys 3-4 times until they are registered. Example: When trying to load Q-Tris from the SD Card, I need to enter normally F L qbin/q-tris.out but now I need to enter F LL qqqbin///q--trisss...outtt, i.e. I sometimes (not predictable when and which key) need to repeat the keys.

When I revert the PR to the old design and synthesize again, then it works fine.

So for now, I reverted the develop branch back to the old design.

Since I consider your design as much more elegant, it would be great, if we could hunt down this bug together :-)

At this moment in time I am stunned:

  • Is your new elegant design maybe faster than my old one and uncovered a timing problem or other kind of glitch that was sleeping in our code since years?

  • Or do we all just overlook some obvious typo?

Always fascinating how hard FPGA development is compared to software development ๐Ÿ˜ˆ

Review/update/correct CONTRIBUTING.md

I created the CONTRIBUTING.md at the master branch, because I thought it belongs there and it might take quite a while until we make our next release (aka update master with real code).

@MJoergen and @bernd-ulmann Please review CONTRIBUTING.md: If you find obvious errors, please correct them directly in the file.

Also, if you have useful additions, please update the file directly.

If there are controversial points - let's discuss them here in this issue.

@MJoergen I invited you to this repo for full write acccess - welcome! ๐Ÿ˜ƒ

P.S. Some of the links in CONTRIBUTING.md are right now (as a temporary compromise solution) pointing to files in the develop branch, just because - as written above - it might take a while until we make the next release V1.6.

CPU bus functional test

This test should verify that the CPU performs the correct read's and write's on the external bus. This is important when addressing I/O devices, and this issue is created as a result of this comment: #9 (comment).

This issue is non-trivial to implement, and is therefore separate from the existing CPU test suite discussed in Issue #9.

Below are the ideas I have so far. I welcome any feedback, improvements, critique, etc. I propose this issue be targeted for release V1.7, simply because we already have a lot of stuff in V1.6.

Proposed solution

A new I/O device will be developed (in both hardware and the emulator) with the following register map:

0xFF80 : Regular R/W scratch register
0xFF81 : Regular R/W scratch register
0xFF82 : Unused (?)
0xFF83 : Unused (?)
0xFF84 : Counts number of reads from 0xFF80. Writeable
0xFF85 : Counts number of reads from 0xFF81. Writeable
0xFF86 : Counts number of writes to 0xFF80. Writeable
0xFF87 : Counts number of writes to 0xFF81. Writeable

Proposed use case

The test code will look something like:

MOVE 0xFF81, R1
CMP 0, @--R1

The above code is expected to perform 1 read from 0xFF80, and no writes. So the test will clear all counters, then perform the above two instructions, and then verify the four counters have the correct values.

The test will then repeat with all instructions and all pairs of addressing modes.

Document programming conventions

Document programming conventions like INCRB/DECRB in sub-routines and making sure the register bank "pointer" points always to the highest used bank, do not program "look aheads"

R8 as default return value for functions

ISRs must not alter any register (use the stack to save/restore)

sysdef.asm for convenient abbreviations

Monitor "OS" calls

; for comments in assembler
optimal columns (take Q-TRIS as example)

name it best-practices and title it "Programming Conventions and Best-Practices"
TODO: doc/best-practices.md

Optimize ROM/RAM usage: Let programs start at 0x2000

Shrink the ROM, currently we could go from 0x0000 to 0x1FFF and still have plenty of room left and let programs start at 0x2000, instead of as this is the case today, from 0x8000 on.

TODO: Before starting with this issue, we need to make a list with obvious and not-so obvious ramifications. Examples:

  1. The ubiquitous usage of RBRA "everywhere" needs to be rethought: RBRA can only jump 32k words forward and backward. This does not matter, as long as programs start at 0x8000 but it does matter, when we switch to 0x2000. So in this example, the minimum we would need to do: Add a warning to the assembler, when one wants to RBRA farther ahead than possible and think again of other ramifiations.

  2. VBCC currently hardcodes 0x8000 at various places in the toolchain

  3. For sure there are a ton more of these nitty-grity details that follow from this issue, so handle with care (and preferably do it in a separate branch)

.DW with undefined label yields no error

The assembler issues no error message in case of a .DW directive which uses an undefined label. Something like

.ORG 0x8000
.DW BLA

yields 0x7FFE in address 0x8000 while it should yield an error.

ISE vs. Vivado Riddle: Instruction-Counter and Cycle-Counter do not work

Description of the Problem

I added a hardware instruction counter and a hardware cycle counter to QNICE-FPGA, so that we can do performance tests. Here is a simple and minimal test program:

https://github.com/sy2002/QNICE-FPGA/blob/develop/test_programs/ise.asm

What happens:

When synthesizing with Vivado, the correct values are being output from the test program. When synthesizing using ISE, complete rubbish is being outout.

Here is the hardware:

https://github.com/sy2002/QNICE-FPGA/blob/develop/vhdl/cycle_counter.vhd

Reproduction Instruction

  1. For being on the safe side: Clone a fresh QNICE-FPGA repo, switch
    to the branch develop (git checkout develop). (Not to be mixed up with dev-int. It needs to be develop)

  2. Compile the toolchain: Run tools/make-toolchain.sh

  3. Compile the monitor: Run monitor/compile_and_distribute.sh

  4. Compile the PORE ROM: Run pore/compile_pore.sh

  5. Go to test_programs and run ../assembler/asm ise.asm. You will need
    the resulting .out file in the following experiment.

Vivado:

  1. Use hw/xilinx/nexys4ddr/Vivado/qnice_nexys.xpr to synthesize a bitstream:
    All good, incl. timing closure.

  2. Start it on hardware

  3. Run the above-mentioned ise.out on hardware

Everything will work like a charm and you will see a hexadecimal output like
this:

   Amount of cycles used:            000000000041
   Amount of instructions performed: 000000000012

ISE:

  1. Use hw/xilinx/nexys4ddr/ISE/env1.xise to synthesize a bitstream:
    All will work fine, too. Incl. timing closure.

  2. Start it on hardware

  3. Run the above-mentioned ise.out on hardware

WOW. Nothing works. You will see an output like

   Amount of cycles used:            FFFCFFFCFFFC
   Amount of instructions performed: FFFCFFFCFFFC

What I already tried

  • Change the speed grade of the Nexys in ISE

  • Cut the clk speed (50 MHz) in half (25 MHz)

  • Read multiple times from the same register to check, if there is a timing problem (doesn't seem to be)

  • Changed (just for testing purposes and reverted back immediatelly) the register bank to synchroneous BRAM. This is in general not a good idea, because then the cpu_test.asm fails and the whole architecture of the CPU would need to be changed, but I just wanted to see, if this might be the reason.

Tristate Refactoring

For 1.7 (or later): As described by Michael in issue #4 ISE vs. Vivado Riddle and #22 Refactor mmio_mux, the fact that we have this nice inout data bus plus the tristate buffers seem to be the reason for more stress and trouble, than it is good.

So we need to refactor this and I suggest that Michael is doing it in V1.7 or later using a new branch then which is a descendant of the then up-to-date develop branch.

Bug in emulator: MOVE clears Carry and Overflow flags.

The source code of the emulator seems to suggest that MOVE instructions should not affect the C (carry) and V (overflow) flags. This is implied from this line of code in qnice.c:

update_status_bits(destination, destination, destination, DO_NOT_MODIFY_CARRY | DO_NOT_MODIFY_OVERFLOW);

However, the MOVE instruction DOES actually modify the C and V flags in that it clears them. This can be most easily seen by running the following sequence of instructions:

MOVE    0x8765, R0
ADD     0x9876, R0
; Now C and V are set
MOVE    0x0000, R0
; Now C and V have been cleared again

The document qnice_intro.pdf does not give any specific details other than words like "last result" and "last operation". I haven't found any more detailed documentation regarding which instructions affect which status flags, so it's not clear to me what the correct behaviour is, but the source code of the emulator is misleading.

Note: This is seen in the latest develop branch.

Assembler Bug: Typo leads to segfault

This code snippet leads to a segfault in the assembler:

        SYSCALL(puthex, 8)

Obviously, it does not like my typo ,8 :-) The output looks like this:

TITANIUM-M5:test_programs$ ../assembler/asm timer_test.asm 
assemble: Line 546: Illegal condition flag! (        ASUB puthex, 8)
../assembler/asm: line 36: 83225 Segmentation fault: 11  $assembler $temp_file $destination

Branch for the fix: dev-int because there, the newest assembler (enhanced while adding the interrupt features) should be located

Emulator won't link on latest dev-io-addr branch

Checking out the latest dev-io-addr branch and compiling the emulator leads to the following error:

timer.c:(.text+0x1aa): undefined reference to `pthread_create'

One possible fix to this is to replace (in make.bash) the line
$COMPILER $FILES -O3 $DEF_SWITCHES $UNDEF_SWITCHES -o qnice
with
$COMPILER $FILES -O3 $DEF_SWITCHES $UNDEF_SWITCHES -pthread -o qnice

Whether this is the correct solution (i.e. whether it works on other Linux distributions) I don't know. I'm using Linux Mint 19.3 (derived from Ubuntu).

Refactor code to remove critical warnings in Vivado

When building for the Nexys4DDR target using Vivado, and viewing the Methodology report gives a number of critical warnings, including:

  1. Non-system clock used to drive flip flops in process count in cycle_counter.vhd.
  2. Asynchronous reset on input to DSP in process write_eae_registers in EAE.vhd.

Quite generally, it is recommended to use synchronous reset rather than asynchronous reset when developing for FPGA, particularly if the asynchronous reset is driven by a LUT, as this could potentially lead to race conditions. However, changing all source files is a major (and non-trivial and potentially bug-introducing) task and requires re-testing everything. Item 2 is mentioned above because Vivado claims to get better optimization possibilities after the change.

So I propose for now that only the two items mentioned above be considered for now. They are rather easy to fix (in the sense that they only require touching a few files), and rather easy to test separately (using eae.asm and ise.asm).

Should this be pushed to the develop branch immediately? I don't think this will cause any merge problems.

It is conceivable (I say hopefully ...) that item 1 above might fix Issue #4 considering that issue is precisely related to the cycle counters.

Emulator crashes on EAE (?) in sierpinski.c

@bernd-ulmann Emulator crashes on EAE (?) in sierpinski.c in branch dev-io-addr. So this might be a problem related to the new MMIO address map.

Reproduction:

  1. Make sure that you PULL the latest dev-io-addr branch so that you have the correct standard C lib (with the updated MMIO address map)
  2. Make sure that you re-run monitor/compile_and_distribute.sh so that you have the correct/updated MMIO address map in dist_kit and that your local monitor.out is fresh
  3. Go to the folder c and enter source setenv.source
  4. Go to the folder c/test_programs and enter qvc qvc sierpinski.c -c99
  5. Go to the emulator folder and enter ./make.bash
  6. Enter /qnice
  7. Enter load ../monitor/monitor.out
  8. Enter load ../c/test_programs/sierpinski.out
  9. Enter run 0
  10. Enter C``R 8000
  11. Enter 495,3,3

You will receive a floating point exception.

TITANIUM-M5:emulator mirko$ ./qnice
Q> load load ../monitor/monitor.out
Unable to open file >>load<<
Q> load load ../monitor/monitor.out^C
Q> load ../monitor/monitor.out
Q> load ../c/test_programs/sierpinski.out
Q> run


Simple QNICE-monitor - Version 0.8 (Bernd Ulmann, sy2002, July 2020)
------------------------------------------------------------------------

QMON> CONTROL/RUN ADDRESS=8000
Sierpinski Fractal Generator
by LambdaBeta in August 2015, adjusted for QNICE by sy2002 in October 2016

Enter bitpattern, scale (2 .. 5) and generation count (0 .. 5).
Here are some value pairs that produce nice results:
 [b, s, g] = 495, 3, 3
 [b, s, g] = 7, 2, 5
 [b, s, g] = 186, 3, 3
 [b, s, g] = 495,3,3

Floating point exception: 8

Make the hardware pass cpu_test.asm

As soon as @MJoergen is ready with test_programs/cpu_test.asm?, @sy2002 will work on making the hardware pass the test. We will start with this, as soon as both branches dev-int and dev-io-addr are merged back to develop, so that this whole thing will be happening on develop.

Bug in emulator: SHR zero bits gives garbage in R14

The following sequence of instructions:

MOVE    0x8765, R1
MOVE    0x00FF, R14
HALT ; Now X correctly contains 1
SHR     0x0001, R1
HALT ; Now X correctly contains 1
SHR     0x0000, R1
HALT ; Now X still contains 1, but should be cleared

leads to X not being cleared as it should. Or should it be unchanged?

Furthermore, the R14 register contains garbage as seen from the following run. It therefore looks like there is an uninitialized variable when shifting by a zero amount. Perhaps the call to write_register() should not take place in this situation?

Q> rdump
Register dump: BANK = 00, SR = MIVNZCX1

	R00-R03: 879f 8765 0000 0000 
	R04-R07: 0000 0000 0000 0000 
	R08-R11: 8000 0be1 0000 0000 
	R12-R15: 0000 feeb 00ff 8005 

Q> run 0x8005
HALT instruction executed at address 8007.

Q> rdump
Register dump: BANK = 00, SR = MIVNZCX1

	R00-R03: 879f c3b2 0000 0000 
	R04-R07: 0000 0000 0000 0000 
	R08-R11: 8000 0be1 0000 0000 
	R12-R15: 0000 feeb 00ff 8008 

Q> run 0x8008
HALT instruction executed at address 800A.

Q> rdump
Register dump: BANK = 170f12, SR = MIVNZC_1

	R00-R03: 0000 c3b2 0000 0000 
	R04-R07: 0000 0000 0000 0000 
	R08-R11: 8000 0be1 0000 0000 
	R12-R15: 0000 feeb 170f12fd 800b 

Implement an MMU

Implement a Memory Management Unit

Step 1: Make architecture

More steps tbd

Recent emulator changes broke SD Card, FAT32 and Q-TRIS

In the last few days, beginning from August 7, on the (not in use any more) branch dev-io-addr, Bernd and Michael worked together to improve the quality of the emulator to fit better to the super thorough (and great) test_programs/cpu_test.asm.

But this came at a price, as mentioned in issue #52: We broke the SD Card code, the FAT32 code and Q-TRIS at an unpredictable amount of lines of code. Just for your reference, here is the line count of the affected files:

TITANIUM-M5:QNICE-FPGA sy2002$ wc -l demos/q-tris.asm monitor/sd_library.asm monitor/fat32_library.asm 
    2228 demos/q-tris.asm
     131 monitor/sd_library.asm
    2134 monitor/fat32_library.asm
    4493 total

And: We might have even more affected files, because my smoke test was super short.

One thing is clear: I will not sift alone through 4493+ lines of code in search for obscure bugs. It can take ages. The FAT32 stuff is non-trivial and also Q-TRIS has its complicated parts. This needs to be a team effort or we need to be smart (and/or revert some decisions to change the behaviour and declare them as "this is how the ISA works ;-) )

It is good, that the three of us will meet soon in an online meeting, because the right way forward in this situation is not obvious and also not trivial, so that I think a verbal discussion / video call is much better then a written discussion in this issue.

For finding a stable basis - a point from where we could start our investigations - I rolled back qnice.c to the last point where my smoke test did not fail but work. @bernd-ulmann : Don't worry, none of your code changes since then is lost. :-) At least when we use the Git GUI that I use (SourceTree), there is a very convenient way to roll forward/backward, see differences, etc.

It did cost me quite some time (more than 1hr) just to find this last point of stable, so here is a wish, that I would like to share: Let's agree that any change to the semantics of any opcode any flag or any other ISA detail and (of course) the emulator automatically leads to someone of the three of us running the following smoke test right after the change was done:

cd emulator
rm qnice-vga
./run-vga.bash
<press enter>
<switch to the terminal screen and type> F R qbin/q-tris.out

Some important notes: rm qnice-vga is necessary to force a rebuild when running ./run-vga.bash. The latter one automatically downloads and mounts a FAT32 disk image.

And then: Play at least something like 60 seconds and clear one row, because funnily enough, one of the bugs that occured lead to not being able to clear any rows any more. Another one lead to the bricks just falling through. So just running Q-TRIS does not help. 60 seconds of gameplay are necessary and save hours of debugging later.

Here is what I found out (everything is related to our "ex branch" dev-io-addr):

The last known good version is from August, 1st and the commit #8711d11

Commit #af2552a from August 7th is interessting: Q-TRIS still works, but FAT32 and/or SD Card do not

Status right now: Branch develop is stable: Everything should work (hardware to be tested, because I was not able to), but all changes to the ISA and to the emulator in qnice.c since August, 1st are rolled back (but not lost).

Simulation: Timer Interrupt Hardware: Test Daisy Chaining Edge Case

Enhance the simulation testbench of the timer interrupt hardware, including dev_int.asm , so that the following daisy chaining edge case is tested:

Timer1 fires. Timer0 fires one (or very little) cycle(s) after timer1.

Expected behaviour: Timer1 is allowed to execute its interrupt. After that, timer0 executes its interrupt.

Add multicolour support in VGA: Hardware and Emu

Changes to programming model:
The print character at VGA$CHAR will be extended to read/write a full 16-bit value instead of as today an 8-bit value. The lower 8 bits will remain the same as before, i.e. the ASCII character code. The upper 8 bits will be divided into two groups of 4 bits as follows:

  • Bits 15-12 background colour, selected from a fixed palette of 16 different colours.
  • Bits 11-8 foreground colour, selected from a (possibly different) fixed palette of 16 different colours.
    In other words, each character may have a separate colour, but no more than 16 (or possibly 32) different colours on the screen in total.

The clear screen function will reset all characters to 0x20 (space) and will assign a default foreground and background colour to each character.

The cursor blink mode will swap foreground and background colour of the character.

Changes to VHDL code:
The video_bram module will have 16-bit data bus instead of 8-bit. This will double the amount of video RAM needed, going from 32 Block RAMs to 64 Block RAMs. Minor changes in vga_textmode.vhd. Most of the changes will be in the vga80x40.vhd module.

Changes to application code:
As written, all application code will break, because the value written to VGA$CHAR must now contain colour information as well in the upper 8 bits. One possible way to avoid this break, is to have different palettes for foreground and background. In other words, selecting both foreground and background colour as 0 would lead to the current behaviour of green on black.

UHS standard

Hello!

Could you please suggest which Xilinx FPGA I can use to implement this design for a UHS standard card?

Thank you!

Fix emulator bug that prevents the timer from starting

In branch dev-int: There seems to be an emulator bug that prevents the timer from starting after a write/read register test:

I added a register write/read test to test_programs/timer_test.asm: When running it at 0xE000 at first all registers are filled with some dummy values and then the dummy values are tested.

The write/read test itself passes, but after the successful write/read test, the timer interrupt's ISR is never called.

Daisy chain leads to Combinatorial Loop warning and no bitstream

Maybe you have a look at issue #47 first, before diving back to work here ;-)

Info about the QNICE interrupt system is in the updated qnice_intro-pdf in branch dev-int, pages 9, 12 and the scheme and timing on pages 23-25.

The QNICE interrupt system is built as a Daisy chain. The more "left" (CPU being the leftmost device) you sit, the more priority you enjoy. This is why it felt very natural for me, to implement the two timers that are specified in sysdef.asm as two Daisy chained timers, as you can see in branch dev-int in the file timer_module.vhd:

   timer0 : timer
   generic map
   (
      CLK_FREQ => CLK_FREQ,
      IS_SIMULATION => IS_SIMULATION
   )
   port map
   (
      clk => clk,
      reset => reset,
      
      int_n_out => int_n_out,          -- connect with "left" device (e.g. CPU)
      grant_n_in => grant_n_in,        -- ditto
      int_n_in => '1', --t1_int_n_out,        -- build Daisy Chain between timer0 and timer 1
      grant_n_out => open, --t1_grant_n_in,    -- ditto
         
      en => t0_en,
      we => t0_we,
      reg => t0_reg,
      data => data
   );

As you can also see, I did comment out the Daisy chain signals of the second timer and instead, terminated the Daisy chain by applying a 1 to int_n_in which translates to "there will never be any interrupt coming from "the right side" of the chain.

I did that, because otherwise, currently there is no bitstream written in branch dev-int: Vivado complains about somethinig that I never heard before and I must admit the googling the term and looking at the forums did not really enlighten me, yet.

Do you have any insights in this phenomenon? What it is? Why it occurs here (did I make some bad mistake and I am just missing the obvious)? How to solve it?

So this is the reason, why right now, there is no Daisy chain and just timer0 while timer1 stays disabled.

If this does not ring a bell on your side - don't worry, then just assign this one back to me and I will continue to investigate.

Bug in emulator: CMP instruction modifies the wrong status bits

This snippet from the emulator:

      if (cmp_0 > cmp_1)
        sr_bits |= 0x0020;  // Set C-bit
      else
        sr_bits &= 0xfffb;  // Clear C-bit

leaves me confused, because 0x0020 is not the inverse of 0xfffb. This is comparing two signed numbers, so should that result be in the C bit or the N bit of the status register ?

Simplify Portability and Maintenance and unify common VHDL code

One of the basic ideas of QNICE-FPGA is, that it is meant to be highly portable. For sure we are not there, yet ;-)
Currently, everything is quite Xilinx specific.

  • Right now, we have two hardware targets: Nexys 4 DDR and MEGA65
  • I assume that there will be more hardware targets in future, because for example the Terasic DE10-Nano dev board is becoming highly popular (and I recently bought one ;-)).
  • And then, the Nexys 4 DDR is deprecated, the successor is called Nexys4 A7: I never tested on it, because I do not have one, yet. We might want to suport the Nexys A7 one day without giving up the Nexys4 DDR support.
  • So the vhdl/hw as well as the hw/xilinx , hw/intel folders might grow in future, making maintenance hard: Particularly due to duplicated and mainly identical files with slight platform specific changes

Is there a way to work in VHDL a bit similar than with the C preproccessor? And then add some build system like CMAKE or the GNU build system?

E.g. in the source files as high level as #ifdef xilinx and/or as low level as #ifdef enable_hdmi and then something like

make nexys4
make MEGA65
make DE10

And the build environment is smart enough to grasp: OK, Nexys and MEGA65 are Xilinx, DE10 is intel...

Can we unite the zoo of vhdl files that right now have been doubled just because I did not know better how to do it? Like uniting MEGA65 globals and env1 globals. Uniting MEGA65_ISE.vhd with MEGA65_Vivado.vhd with env1 ISE and Vivado and so on.

Having some vhdl/hw/common folder where all the common stuff resides and then the TRULY hardware specific stuff, such as HDMI and HyperRAM for MEGA65 then in a vhdl/MEGA65 folder.

Feature Request: Add interrupt when VGA retraces specific scan line

Changes to programming model

Add a register (IO memory address) that reads back the scan line currently being displayed.
Add a (same or separate?) register to store the value of a specific scan line.
Add registers to enable/disable interrupts when current scan line is equal to configured scan line.

This should probably be implemented AFTER Issue #17.

Fix emulator bug in software interrupt (INT)

@bernd-ulmann The emulator seems to struggle either with post increments at software interrupts or with two software interrupts in a row (or with something else)

Switch to branch dev-int and pull: I enhanced test_programs/int_test.asm like this:

        [...]
        MOVE    PREDECIND_1, R8 ; Test indirect ISR address with predecrement
        INT     @--R8

        INT     @R8++           ; test postincrement during INT
        INT     @R8

        MOVE    ITEST_3, R8
        SYSCALL(puts, 1)
        SYSCALL(exit, 1)

And while doing so, I also added an appropriate ISR to which @R8++ should point to and made sure that R8 is pushed on the stack during the PRE ISR, so that the correct R8 should still be available when doing the post increment.

The resulting output of the new test program should be:

QMON> CONTROL/RUN ADDRESS=8000
Start
ISR_ABS
ISR_REG
ISR_IND
ISR_PRE
ISR_PRE
ISR_POST
End

QMON> 

But in fact, the last three outputs before End are three ISR_PRE in a row.

Monitor built-in disassembler should convert relative addresses

When disassembling code using the Monitor's built-in disassembler, relative addresses are shown as just that: relative.

I would like the disassembler to show the corresponding absolute address. For instance, the command "M S 0000 0060" currently shows:

0000 FFA0 RBRA    005A 1
...
005A FFA0 RBRA    0E88 1
005C 9FB8 AND     00FF R14 

The instruction at 0000 jumps to address 005C. Showing the relative address (005A) makes the output harder to read.

This applies to the instructions RBRA and RSUB. The instructions ABRA and ASUB already show the absolute address. Alternatively, the relative instructions could show both the offset AND the absolute address, to make the distinction more clear.

Tentatively assigned to V1.7 if you agree.

Please add yourself to the README.md's Acknowledgements section

Hey Michael, you for sure already now earned yourself a good spot in the QNICE hall of fame :-) So here is another small task for V1.6: Please add yourself to the README.md's Acknowledgements section: The one that is shown when you scroll down to the very end of the main README.md. Please do it in branch develop.

Perform Smoke Tests on merged branch develop

Gentlemen, I did it!! I merged dev-int and dev-io-addr into develop this evening! ๐Ÿฅณ ๐ŸŽ‰ :bowtie:

There was astonishingly little trouble in the merging itself, because both of you were so disciplined, when committing to the different branches. So thank you very much for that!

That means we do not need the branches dev-int and dev-io-addr any more .

I am pretty sure, that we do not have merge errors, i.e. wrong versions or so. I double checked each file and when in doubt I used line-by-line merge and comparison tools such as Araxis Merge.

But I guess we all need to perform some smoke tests on develop now - also and in particular, because I did all this work at a place, where I don't have an FPGA at hand, so all I could test was on the level of the emulator.

Michael, if you ever wanted to reproduce this cool "dual monitor" setup including a "jumping ball" on top of Q-TRIS on your own hardware: This might be the time, here is the comment that I mean:

#47 (comment)

BUT - as always, when so many changes have been done: Something broke. Not because of the merge! But because of the change in behaviour of the emulator. Since this has nothing todo with the merge itself, I opened a new issue for that called "Recent emulator changes broke SD Card, FAT32 and Q-TRIS". Let's use the new issue (issue #53) to discuss and work at that.

Let's use this issue at hand for all other smoke test results on the merging itself. I assume the merging itself worked pretty fine and we will be able to close this issue rather sooner than later. But I fear that issue #53 will be with us for a little longer.

There is a question to Michael about the old branches: So far, I never dared to delete any old branch due to the fear of loosing the history and due to the fact that I do not know how to do it right. Do you have experience with GitHub's behaviour about that in conjunction with the underlying Git? Bernd and I do not. So if you do: We might want to discuss also the deletion of old branches here in this issue before closing. Otherwise, let us just let them be for a little longer until we dare to proceed :-)

Feel the joy: Hardware Timer Interrupt

Gentlemen, this is an unusual "issue". It is just meant to share some joy with you about the first (still work-in-progress) version of the hardware timer interrupt in branch dev-int: This branch now successfully runs test_programs/test_int.asm (software interrupts) and test_programs/timer_test.asm (hardware timer interrupts). But this is by far not all ;-) Read on!

IT IS SOOOOOO FREAKING AWESOME TO SEE. ๐Ÿ˜ƒ

Here is what I did:

  1. Synthesized the Nexys 4 DDR Version in dev-int and start it on the FPGA
  2. STDIN/STDOUT => UART (SW0 and SW1 are OFF)
  3. Assemble test_programs/timer_test.asm
  4. Connect via terminal program to UART and M L paste the timer test .out into the terminal window and start it via C R E000

The output that then comes on serial is:

QMON> CONTROL/RUN ADDRESS=E000
Setup timer 0 to interrupt every 1000 milliseconds.

QMON> Timer 0 has issued interrupt request #0001
Timer 0 has issued interrupt request #0002
Timer 0 has issued interrupt request #0003
Timer 0 has issued interrupt request #0004
Timer 0 has issued interrupt request #0005

This is already pretty cool. But hang on, it gets cooler: Of course, the monitor is still working fine, as we are talking about real hardware timer interrupts. So even if the ISR spills our terminal window, the QMON> prompt still works.

So - in my Nexys board, I have a FAT32 formatted SD Card, so I entered, while the ISR continues "spilling" and actually interrupting my while I type ๐Ÿ˜‚ F R qbin/q-tris.out as you can see here

Timer 0 has issued interrupt request #0013
Timer 0 has issued interrupt request #0014
FILE/Timer 0 has issued interrupt request #0015
RUN: qbTimer 0 has issued interrupt request #0016
in/q-tTimer 0 has issued interrupt request #0017
ris.outTimer 0 has issued interrupt request #0018

Timer 0 has issued interrupt request #0019
Successfully loaded qbin/q-tris.out from 8000 to 91E3
Running...
Timer 0 has issued interrupt request #001A
Timer 0 has issued interrupt request #001B
Timer 0 has issued interrupt request #001C

(The ISR sits above E000 and Q-TRIS loads to 8000 to 91E3, so no overlap.)

And then - I can play Q-TRIS on the VGA screen, while on the terminal, it keeps counting. Slowly and steadily. Kind of a "multi monitor setup": VGA = Q-TRIS and UART = show ISR output. And of course you do not feel any disturbance because with our ~12 MIPS @ 50 MHz, QNICE is surely fast enough for that.

What a joy ๐Ÿ˜„

And then, in the end, the whole thing is deactivated by running C R E100 as seen here:

Timer 0 has issued interrupt request #007C
Timer 0 has issued interrupt request #007D

QMON> Timer 0 has issued interrupt request #007E
Timer 0 has issued interrupt request #007F
Timer 0 has issued interrupt request #0080
CONTROL/Timer 0 has issued interrupt request #0081
RUN ADDRESS=ETimer 0 has issued interrupt request #0082
100

QMON> 

As soon as both of you have seen/read this - one of you can close the issue ;-)

Release 1.6: Scope

The latest stable release is V1.5. Currently, we have a ton of loose ends, so let us use this issue to define the scope of release 1.6 and track the progress towards release 1.6. Let's not start even more loose ends (such as removing the tristates everywhere) right now: We might soon open a second issue "Release 1.7: Scope" where we put all the stuff that takes longer.

Original intend of release 1.6 (branch develop)

Originally, I started release 1.6 with the goal to port QNICE-FPGA to the MEGA65. Before being able to do that, I needed to port it to Vivado first and before being able to do that, I needed to create the hw folder including hw/README.md where I did split the multiple FPGA hardware types and the build environment. Also the vhdl/hw folder was created to host hardware specific code. When porting QNICE-FPGA to the MEGA65 I also improved a lot of documentation. And I made the whole toolchain Linux friendly.

Have a look at the work-in-progress VERSIONS.txt in the develop branch, it contains a rough "What has already been done" and what is still to be done list.

What is already finshed from the original intend of V1.6

Here is the summary of what has already been done for V1.6 which is part of the develop branch:

  • MEGA65: Ported QNICE-FPGA to the MEGA65 (https://mega65.org/)
  • UART: Added a 32 Byte FIFO to the UART. This was necessary because the
    MEGA65 serial over JTag does not support RTS/CTS and therefore we needed
    more stability. Now RTS/CTS should be unnecessary in most cases.
  • INSTRUCTION COUNTER: Added. Counts all instructions executed by the CPU.
    Can be used for performance testing as shown in
    test_programs/q-tris_perf_test.asm and test_programs/mandel_perf_test.asm.
  • EMULATOR: Made the WebAssembly target compatible with Emscripten 1.39.14
    (and newer and it still works with 1.39.10 and some of the older versions,
    but not with the versions in between). The background of this phenomenon is
    explained here: emscripten-core/emscripten#10746
  • TOOLCHAIN: qtransfer: Convenient mechanism for transferring software
    (.out files) from the host computer to QNICE-FPGA. Details: doc/README.md
  • TOOLCHAIN: Added Xilinx Vivado as an alternative IDE to work with.
    Structured all hardware dependencies in the new folder 'hw' and added
    a documentation in 'hw/README.md'.
  • TOOLCHAIN: Added Ubuntu Linux support, which means it should also run on
    any other Debian based distribution. You might want to install xclip for
    more convenience (.out copied to clipboard after assembler ran).
  • DOCUMENTATION: Added doc/README.md, hw/README.md & vhdl/hw/MEGA65/README.md

What needs still to be done to finalize the original intend of V1.6?

  • EMULATOR: Correct emulator speed: Using the cycle and instruction counter, we found out that the actual MIPS of the QNICE hardware is not equal to 12.96 MIPS. Correct that in the VGA and WASM versions of the emulator.
  • MEGA65 HyperRAM: The HyperRAM driver is not fully stable yet: Stabilize it (8bit native HyperRAM version) and make the 16bit QNICE version stable. Update the appropriate test programs. If time and energy left: Finalize "The Matrix" ASCII video as a demo for the HyperRAM
  • Make sure that the PORE texts are correct (for the MEGA65 version as well as for the standard version)
  • Restructure dist_kit and have .bit and .cor files ready and then update all the links for example in the hw/README.md and doc/README.md (are there more?)
  • Make sure to update the Getting Started section to reflect all the news about ISE and Vivado and also about the platforms. Have also a MEGA65.bit and a MEGA65.cor in the dist_kit and mention it in the Getting Started section

Interrupt system for V1.6 (branch dev-int)

In branch dev-int we are developing the QNICE interrupt system as it is described on pages 9, 12, 23-25 in this updated version of the intro document.

Interrupt system: Already finished

  • Assembler is updated to support the new instructions
  • Intro document, programming card updated
  • Emulator improved to support the interrupt system
  • Two test programs are written: test_programs/int_test.asm to test the software interrupts in all forms and shapes and test_programs/timer_test.asm to test hardware interrupts using the timer
  • Hardware: Development testbed created in vhdl/sim: Everything related with the development of the interrupt system is called dev_int*: The asm file is the test progrram, the dev_int.vhd file is the top file for the simulation.
  • Hardware: The CPU successfully supports hardware and software interrupts

Interrupt system: TODOs for V1.6

  • Hardware: Finalize the work-in-progress (WIP) hardware timer module timer_module.vhd and timer.vhd, particularly: Implement the correct Daisy Chaining mechanism and behaviour and rename the left right logic of the Daisy Chain in in and out
  • Test the hardware (at least using the above-mentioned test programs)
  • Is there a cool demo program that we could write to show off the interrupt system?

Change the memory map and refactor MMIO registers (branch dev-io-addr)

The goal is to have a more structured (and hardware implementation friendly) memory map. Issue #18 is tracking the progress.

What has been done already

  • Define new memory map in monitor/sysdef.asm
  • Fix legacy test programs that used hardcoded MMIO addresses
  • Fix the emulator by including ../dist_kit/sysdef.h instead of using hardcoded own #defines to access registers
  • Add MEGA65 MMIO to sysdef.asm
  • Updated programming card
  • Updated README.md

What remains to be done

  • Refactor keyboard.vhd
  • Update MMIO hardware
  • Search for old addresses in the comments in the VHDL files (e.g. keyboard.vhd) and replace them all
  • Test the updated MMIO hardware
  • MEGA65: Update the hardware, update the test programs, retest on hardware
  • Recompile standard C library
  • Perform some smoke tests for the recompiled standard C library
  • Recompile all /qbin demos and tools and check-in the new /qbin
  • Create a new disk image as described here
  • Modify emulator/run_vga.bash to support the new disk image
  • Put the new disk image also to the two standard SD card (Nexys4DDR and MEGA65) and test them there
  • Do not update the website http://qnice-fpga.com/emulator.html as nobody would notice the MMIO change there, BUT: We need to update the source code to download the V1.6 version of the disk image (with the old memory map, as the online demo of the emu is still working in the old world). Then: Do a smoke test locally by recompiling and testing the WebAssembly version of the emulator.

STDIN switch during input

Make IO$GETCHAR smarter, so that switching STDIN does not require "one last keypress" on the old STDIN any more before reading from the new STDIN

Bug in emulator: Overflow calculation during SUB is incorrect

The following snippet of code:

MOVE    0x0005, R1
MOVE    0x0007, R2
SUB     R2, R1

calculates the subtraction 5-7 and gets the correct result -2 (represented as FFFE), but the overflow flag is set. In this calculation there is no overflow, and the overflow flag should be clear.

I assume the overflow flag should work just as on the 6502 processor. From the document http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html I have extracted this excerpt:

The formulas for overflow during addition given earlier all work for subtraction, as long as the second argument (N) is ones-complemented. Since internall subtraction is just addition of the ones-complement, N can simply be replaced by 255-N in the formulas.

This could perhaps be used as part of the fix in the emulator.

Feature Request : Add FIFO to keyboard I/O

The current design only stores the last pressed key. If the user presses multiple keys before the program reads from the keyboard device, then some key presses will be lost.

A small 32-byte FIFO just like the UART will take care of this.

All VHDL files: Consistent line endings

Let's have consistent line endings in all VHDL files from version 1.6 on. But CAUTION: Let's do this change as one of the last changes we do, right before releasing. Reason: If we did it right now, we would have so many changes to soo many files that the process of merging dev-io-addr plus dev-int plus develop plus master would be a nightmare.

The reason why all these files are so scrambled, when it comes to line endings: I developed pre V1.6 with ISE under Windows. In V1.6 I switched to Vivado on Linux.

@MJoergen I guess Linux endings are fine, as all of us seem to run Vivado on Linux. I never did a "line ending change" in past and I assume you have some tool or something with which you could do that?

Part of release scope 1.6, issue #28

Branch to execute this on: develop but only after dev-io-addr and dev-int are 100% done, tested and merged.

Timer Interrupt Hardware: Check Edge Cases and Stability

While implementing the timer interrupt hardware I noticed, that during the "Interrupt Grant Phase" when the CPU's IGRANT_N goes to 0 we need to de-couple all other devices from the DATA bus. Otherwise we might have a data clash on the bus.

Right now this logic is implemented in mmio_mux by making sure that all the devices, including RAM and ROM and PORE are not enabled (i.e. the devices en = 0 and of course we = 0).

I did not fully think through all edge cases.

For example what about the whole topic of cpu_wait_for_data in mmio_mux. On a first glance and thought, it looks innocent, but at least uart_cpu_ws needs a second thought or in general the question: Will a disabled device automatically lead to correct behavuour in (a) all contexts and (b) in the particular context of cpu_wait_for_data?

Are there more edge cases?

This topic has the potential for unpredictable crashes and nearly non-debuggable strange behaviour.

I ran into it when I tried to bring the hardware timer interrupt to life on real hardware. While in the simulation, everything worked like a charm, on hardware, literally nothing worked.

Therefore I plan to leave this issue open for a few releases and go forward like this:

  1. For V1.6: When everything is merged to develop and seems to work, rethink this and think about edge cases.

  2. After releasing V1.6, do not close this but re-label it to V1.7. Rethink the edge cases again, also in the context of the tristate-refatoring in issue #30 .

  3. If possible for V1.7, write some timer interrupt stress test, that tries to provoke the edge cases, such as having timer activity while heavily working with the UART and it's uart_cpu_ws and similar with RAM/ROM and it's wait-for-data equivalents

  4. If all is good in V1.7, too, then we can think about closing this issue - or - pushing it forward one more release, just not to forget about it

Change the memory map and refactor MMIO registers

EDIT 31.7.20, 21:57: Changed/Updated TODO LIST

@bernd-ulmann @MJoergen

Here are all steps necessary that came to my mind spontaneously. Please add your thoughts, maybe I forget something:

DONE BY SY2002 and VAXMAN Let's discuss the new Memory Map in monitor/sysdef.asm here based on the assumption: The standard is 8 words for 8 registers per device, but we also allow devices to have 16 words. 256 words of MMIO space starting at FF00.

  • This will break all existing code, but a simple recompile should fix it.

DONE BY VAXMAN * There are some programs in test_programs that still use hard-coded registers and the emulator also uses hardcoded register addresses: We need to sift through them and fix them.

DONE BY VAXMAN * The emulator should include ../dist_kit/sysdef.h (**) instead of using hardcoded own #defines to access registers

  • Recompile standard C library

  • Update MMIO hardware

  • Recompile all qbin files and update it in GitHub

DONE BY SY2002 Add MEGA65 MMIO to sysdef.asm and adjust MEGA65 samples and VHDL CODE

re (**) @MJoergen : FYI: The file monitor/sysdef.asm is the single source of truth. There is a script called monitor/compile_and_distribute.sh which is copying monitor/sysdef.asm to dist_kit/sysdef.asm and while doing so also generates a dist_kit/sysdef.h for being used e.g. in the emulator but this dist_kit/sysdef.h is also used in the implementation of the standard C library of QNICE that you find in c/qnice (off-topic and by the way, a small intro how to use the C compiler is here: https://github.com/sy2002/QNICE-FPGA#programming-in-c)

Correct typo in qnice_intro.pdf

Please fix in our interrupt dev branch dev-int:
Correct typo in qnice_intro.pdf
On page #12, it states "All control instructions share the opcode D.".
I guess correct would be "E" instead of "D".

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.