darklife / darkriscv

opensouce RISC-V cpu core implemented in Verilog from scratch in one night!
BSD 3-Clause "New" or "Revised" License
2.07k stars 281 forks source link

Works on DE0 Nano Altera Cyclone IV #31

Closed abehnke closed 11 months ago

abehnke commented 3 years ago

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.

samsoniuk commented 3 years ago

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?

abehnke commented 3 years ago

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!

samsoniuk commented 3 years ago

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!

zappos23 commented 3 years ago

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

samsoniuk commented 3 years ago

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.

zappos23 commented 3 years ago

Hi @samsoniuk,

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

zappos23 commented 3 years ago

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 % )

zappos23 commented 3 years ago

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

zappos23 commented 3 years ago

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

abehnke commented 3 years ago

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.

samsoniuk commented 3 years ago

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.

zappos23 commented 3 years ago

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.

zappos23 commented 3 years ago

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 % )

samsoniuk commented 3 years ago

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

zappos23 commented 3 years ago

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')

samsoniuk commented 3 years ago

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!

zappos23 commented 3 years ago

THanks @samsoniuk ! it's working!

mr-rajashekhar commented 1 year ago

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.