darklife / darkriscv

opensouce RISC-V cpu core implemented in Verilog from scratch in one night!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Works on DE0 Nano Altera Cyclone IV

abehnke opened this issue · comments

I could not find any reference to somebody trying this on the Altera brand of FPGA. (I did not want to buy another kind of FGPA and download yet another gigantic development environment.) The pre-built demo program works fine at 50Mhz. In the config.vh, I turned off THREADING - just to keep things simple. The only change I made was to install the PLL clock generator code and mess with the RES (reset) to connect it to a button on the DE0 Nano board.

BTW I first did this by stripping out most of the 'ifdef' so that I could follow the code with more ease. This was interesting since I made errors which resulted in much fun with ModelSim. Learned much more than if it had just worked.

Thanks for this cool project. Sorry to place this in the ISSUES but I could not figure out another good place for a comment.

Wow! Thank you!

I am very curious about how much LUTs the DarkRISCV requires in the Cyclone IV and how fast it can runs! Can you share the synthesis report generated by the Altera tool?

I tried 100Mhz with the result that just junk appeared on the output. Strangely, the LEDs were slowly counting up in binary. My knowledge about the FPGA world is minimal. For the Quartus Prime, I only use "Start Compilation" and "Programmer". Some of its outputs show red - don't know what that means but one of the items: "Multicorner Timing" showed a min. pulse width of 9.4. I assume that is nanoseconds. If so then the limit is 100Mhz.

When I tried 75Mhz, it ran with no problems.

I have the following 3 defines set: 3STAGE, MAC16X16, RV32E

My goal is just to learn about processor design so speed is not too important to me at the moment.

Below is one of the summary reports. I can send them all if you want.

====

Flow Status Successful - Fri Oct 09 13:10:39 2020
Quartus Prime Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition
Revision Name darkriscv_d
Top-level Entity Name darkriscv_d
Family Cyclone IV E
Device EP4CE22F17C6
Timing Models Final
Total logic elements 3,026 / 22,320 ( 14 % )
Total registers 1014
Total pins 47 / 154 ( 31 % )
Total virtual pins 0
Total memory bits 131,072 / 608,256 ( 22 % )
Embedded Multiplier 9-bit elements 2 / 132 ( 2 % )
Total PLLs 1 / 4 ( 25 % )

=====

   INSTRUCTION SETS WANT TO BE FREE

boot0: text@0 data@4148 stack@8192
board: unknown (id=8)
build: darkriscv fw build Sun, 20 Sep 2020 09:04:24 -0300
core0: darkriscv@75.0MHz with rv32e+MAC
uart0: 115200 bps (div=651)
timr0: periodic timer=1000000Hz (io.timer=74)

Welcome to DarkRISCV!

I found a DE Nano w/ Cyclone IV here... I will try install the Intel tools and make some tests. Maybe is possible optimize something else for this FPGA in order to get more performance!

hello! This is interesting!
i got a de10 lite and wish to try it out too... hoping that i can get some advice from you guys.
Is it necessary to have a pll clock generator definition in the rtl? can i just directly connect (pin map) it to the board clock which is 50Mhz? thanks

hi @zappos23

The clock generator is not required, for example, in the config.vh you can find boards that are clocked directly from a 50MHz the board oscillator:

ifdef LATTICE_BREVIA2_XP2
define BOARD_ID 5
define BOARD_CK 50000000
define INVRES 1
endif

ifdef DIGILENT_SPARTAN3_S200
define BOARD_ID 7
define BOARD_CK 50000000
endif

As long the BOARD_CK is defined, the SoC will use it in order to automatically calculate the baud-rate divisor for the 115200bps UART and to initialize some registers that shows the core clock in the firmware demo.

The PLL clock generator is used mostly in the Xilinx FPGAs as performance demonstration, but typical real world applications work well with smaller clocks.

Hi @samsoniuk,

Thank you so much for your quick reply. And thank you for the info!!! i will give it a try.

Hi @samsoniuk, @abehnke,

Do you guys know why i am getting such a large total logic elements and registers?
I wonder if i am missing any settings.
Thanks!

Flow Status Flow Failed - Fri Feb 05 13:20:25 2021
Quartus Prime Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
Revision Name darksocv
Top-level Entity Name darksocv
Family MAX 10
Device 10M50DAF484C7G
Timing Models Final
Total logic elements 164,573 / 49,760 ( 331 % )
Total registers 66529
Total pins 12 / 360 ( 3 % )
Total virtual pins 0
Total memory bits 0 / 1,677,312 ( 0 % )
Embedded Multiplier 9-bit elements 0 / 288 ( 0 % )
Total PLLs 0 / 4 ( 0 % )
UFM blocks 0 / 1 ( 0 % )
ADC blocks 0 / 2 ( 0 % )

i wonder if it's cause by the ROM being synthesized by Quartus

hi @abehnke,
May i know how do you infer the ROM in quartus? in my run quartus is synthesizing the 32x2048 bits ROM. THanks.

I used the code as given by Samsoniuk. Note: as I mentioned in the first comment, I removed the 'ifdef'. So, for example, what I have is:

// ro/rw memories

`
reg [31:0] MEM [0:2047]; // ro memory

// memory initialization

integer i;
initial
begin
    for(i=0;i!=2048;i=i+1)
    begin
        MEM[i] = 32'd0;
    end

    $readmemh("darksocv.mem",MEM);
end

I hope this helps.

Hi @zappos23

I guess the problem regards to a change that I inserted last week! Try activate the RMW mode by uncommenting the option RMW_CYCLE in the line 79 of config.vh.

thanks @abehnke , @samsoniuk.

hi @samsoniuk,
After implemented your suggestion, i still see the RAM is not getting inferred. But i came across this line of message:
Info (276014): Found 1 instances of uninferred RAM logic
Info (276013): RAM logic "MEM" is uninferred because MIF is not supported for the selected family

It looks like the darksocv.mem file format is not recognized by quartus.

In my testing i went and remove the line readmemh, then the RAM got inferred but failed in subsequent stage due to uninitialize memory.

Do you know how can i convert the mem file format to intel quartus HEX or MIF file format?

Thank you.

hi @samsoniuk .

Managed to got it working...
Apparently i need to do these extra steps to getting in working:

  1. convert the darksocv.mem to mif format. I wrote a simple script to convert that.
  2. reading mif in verilog.
    -> (* ram_init_file = "darksocv.mif" *) reg [31:0] MEM [0:2047];
    -> Need to change the quartus settings to get it working.
    assignment > device > Device and pin options > configuration mode
    to
    "Single Uncompressed Image with memory initialization (512 Kbits UFM)"

Below are the results running at 50Mhz clk:
Revision Name : darksocv
Top-level Entity Name : darksocv
Family : MAX 10
Device : 10M50DAF484C7G
Timing Models : Final
Total logic elements : 2,878 / 49,760 ( 6 % )
Total combinational functions : 2,677 / 49,760 ( 5 % )
Dedicated logic registers : 929 / 49,760 ( 2 % )
Total registers : 929
Total pins : 12 / 360 ( 3 % )
Total virtual pins : 0
Total memory bits : 65,536 / 1,677,312 ( 4 % )
Embedded Multiplier 9-bit elements : 0 / 288 ( 0 % )
Total PLLs : 0 / 4 ( 0 % )
UFM blocks : 0 / 1 ( 0 % )
ADC blocks : 0 / 2 ( 0 % )

Hi @zappos23

Wow! Very good!

I guess @abehnke found no problems because the Cyclone IV appears to accept the traditional syntax! Anyway, that differences are not surprise, as long the other tools have lots of differences too, in a way that I need add defines for different tools and technologies (VIVADO, XILINX7, ICARUS, etc).

My suggestion is add something like:

ifdef INTEL10
the Intel series 10 syntax
else
the existing syntax
endif

In a way that the board definition in the config.vh will enable the different features. As example, see the Artix-7 A35 board definition:

ifdef QMTECH_ARTIX7_A35
define BOARD_ID 9
define BOARD_CK_REF 50000000
define BOARD_CK_MUL 20
define BOARD_CK_DIV 10
define XILINX7CLK 1
define VIVADO 1
define INVRES 1
endif

There are lots of differences from the standard Spartan-6 environment (different clock manager, different tool, etc).

Feel free to merge your changes and add comments! :)

Thanks,
Marcelo

Thanks @samsoniuk on the feedback!
Sure!! But i am new to github and i have no knowledge to merge changes. Would you mind to share the steps to do so?

I managed to get the FPGA board talks to a raspberry pi through UART gpio pins. And it works perfectly!! Thank you so much for sharing the code, design and steps!
But i am nothing getting right response from the FPGA after writing 'mul 3 2' to it. Below is the output from my raspberry pi terminal:

Do you know if i am doing it correctly? Thanks

read data: b'boot0: text@0 data@6224 stack@8192 (1968 bytes free)\r\n'
read data: b'board: simulation only (id=0)\r\n'
read data: b'build: Mon, 01 Feb 2021 04:06:48 -0300 for rv32e\r\n'
read data: b'core0/thread0: darkriscv@50.0MHz rv32e\r\n'
read data: b'uart0: 115200 bps (div=434)\r\n'
read data: b'timr0: frequency=1000000Hz (io.timer=49)\r\n'
read data: b'\r\n'
read data: b'Welcome to DarkRISCV!\r\n'
read data: b'> 3mul 2 3mul 2 3mul 2 3mul 2 3'

Below is how i use python to write to fpga:
while True:
response = ser.readline()
print("read data: " + str(response))
ser.write(b'mul 3 2')

Hi @zappos23

The line is read by a gets() function in the darkriscv side, which requires a \n after each command send in order to return the entire line to be parsed by the command line interpreter. So, you can try replace the ser.write() by ser.writeline() or try add a \n in the string, something like b'mul 3\n'... I am not expert in python, but I guess one of that will work!

THanks @samsoniuk ! it's working!

Hi @zappos23, which version of Quartus are you using?
I am using 20.1, and I cannot find the option of "Single Uncompressed Image with memory initialization (512 Kbits UFM)". I am only seeing standard and remote.