User Tools

Site Tools


minsoc_faq

MinSOC FAQ

Adaption

How to adapt the firmware to my implementation?

Answer:

  1. Edit minsoc/sw/support/orp.ld line 14 LENGTH = 0x00006E00 to accord with your memory amount in Bytes taking ORIGIN into account. Memory amount in Bytes is given as 4⋅2MEMORYADRWIDTH, where MEMORYADRWIDTH is defined in `define MEMORY_ADR_WIDTH in “minsoc/rtl/verilog/minsoc_defines.v”:
    LENGTH = 4⋅2MEMORYADRWIDTH - ORIGIN(0x00001200)
    (e.g. 4⋅213 = 32,768 Bytes = 0x8000 | LENGTH = 0x8000 – 0x1200 = 0x6E00)
  2. Select your STACK size on “minsoc/sw/support/board.h” line 16 #define STACK_SIZE 0x01000
  3. Change your IN_CLK on “minsoc/backend/board.h” if not using 25000000 (25MHz).

How to configure the simulation

Answer:

  1. Configure your system: “minsoc/rtl/verilog/minsoc_defines.v”
    You can uncomment ETHERNET on “minsoc_defines.v” to input data to the SoC's Ethernet interface and read data from it.
  2. Configure “minsoc/bench/verilog/minsoc_bench_defines.v”
    1. Your testbench will use a memory model, not actually the same memory controller the implementation uses. This enables the option “`define INITIALIZE_MEMORY_MODEL”, where the firmware is loaded to the memory before testbench start.
    2. You may use the actual implementation memory:
      • Comment “`define INITIALIZE_MEMORY_MODEL”
      • Edit “minsoc/sim/run/generate_bench”
        Substitute “../bin/minsoc_model.txt” for “../bin/minsoc_memory.txt”
      • You might want to uncomment “`define START_UP”, it loads the firmware to a SPI memory. At start of testbench the system reads this memory and loads the firmware to main memory. Takes +-3 min. This is possible to be used for a real system, all you have to do is uncomment “`define START_UP” from “minsoc/rtl/verilog/minsoc_defines.v”.
  3. Modify testbench as you please.
    Please refer to minsoc.pdf chapter 4 Simulation for more information.

Is it possible to debug the simulation as I debug the firmware running on my board?

Answer: Yes. Open 3 terminals:

  1. Terminal 1: from minsoc/sim/run/
    ./generate_bench
    ./run_bench <your_firmware.hex> (e.g. ./run_bench ../../sw/uart/uart-nocache-twobyte-sizefirst.hex)
  2. Terminal 2: from minsoc/sim/run
    ./start_server
  3. Terminal 3: at minsoc /sw/uart 1)
    or32-elf-gdb uart-nocache.or32
    target remote :9999
    load
    set $pc=0x100
    c

Furthermore, if you have waited for the either of the following messages on Terminal 1 before you start with Terminal 2:

  • Memory model initialized with firmware:
  • Memory start-up completed…

you can skip the “load” part of Terminal 3.

Problems

I have generate bench errors, what happened?

Answer:

foo@hostname:~/minsoc/sim/run$ ./generate_bench
../../bench/verilog/minsoc_bench.v:590: error: Could not find variable
"minsoc_top_0.or1200_top.or1200_cpu.or1200_rf.rf_a.ramb16_s36_s36.mem" in
"minsoc_bench.init_fpga_memory"
../../bench/verilog/minsoc_bench.v:591: error: Could not find variable
"minsoc_top_0.or1200_top.or1200_cpu.or1200_rf.rf_b.ramb16_s36_s36.mem" in
"minsoc_bench.init_fpga_memory"
2 error(s) during elaboration.
foo@hostname:~/minsoc/sim/run$

You tried to use the Xilinx RAM or your specific memory, by uncommenting the 'define OR1200_XILINX_RAMB16 or others in the minsoc/rtl/verilog/or1200/rtl/verilog/or1200_defines.v file.

On or1200_r3 the register file, or1200_rf.v, always instantiates a generic memory for DUAL PORT RAM. Previously it instantiated a target specific or generic memory depending on your sets of or1200_defines.v.

Since the CPU does not work if the registers aren't set to zero previous to simulation start, my testbench especifically set the memory content of the registers to zero, before simulation start. I didn't try to find out why this is like that, I only noticed it was that way.

First, I commented out the initialization for dual port RAM to test if the new memory would work. The simulation failed as it did before.

I could include a new initialization for the new memory. Because the new memory is generic and I believe target specific memory should be used whenever possible, I'd recommend you to switch it back to the way it was before and not to touch the memory initializations:

On or1200_rf.v: lines 304 and 280 edit this way:

  1. line 304:
//
// Instantiation of register file two-port RAM B
//
/* or1200_dpram #
(
.aw(5),
.dw(32)
)*/
or1200_dpram_32x32
rf_b
(
.rst_a(rst),
.rst_b(rst),
.oe_a(1'b1),
// Port A
.clk_a(clk),
.ce_a(rf_enb),
...
  1. line 280:
//
// Instantiation of register file two-port RAM A
//
/* or1200_dpram #
(
.aw(5),
.dw(32)
)*/
or1200_dpram_32x32
rf_a
(
.rst_a(rst),
.rst_b(rst),
.oe_a(1'b1),
// Port A
.clk_a(clk),
.ce_a(rf_ena),
...

This might be a typo or maybe a work around for something else. That's something the OpenRISC developers have to tell us. It is remarkable that both, OR1200_RFRAM_GENERIC and OR1200_TWOPORT are exactly the way they were before. However, the OR1200_RFRAM_DUALPORT uses now a new module, which is basically an adaptation of the OR1200_RFRAM_GENERIC one, but with DUALPORT, of course.

MinSoC firmwares won't compile.

Answer: there are two versions of GCC right now. The older version adds a leading underscore to C functions in its assembly counterpart and the other does not. MinSoC firmware includes assembly files which access C functions using the leading underscore being compatible with the older version. If you have the new version GCC, remove the underscores of C functions being accessed by the assembly. The error output of GCC will tell you which are the functions whose underscore you have to remove.

My device is full, can I reduce the used logic of the SoC?

Answer: yes

  1. Configure minsoc/rtl/verilog/or1200/rtl/verilog/or1200_defines.v (recommended values for different devices here)
    1. Target FPGA memories (OR1200_XILINX_RAMB16 for Xilinx, Spartan 3 and above, OR1200_ALTERA_LPM for all Altera)
      (if you do this, check: I have generate bench errors, what happened?)
    2. Type of register file RAM (OR1200_RFRAM_GENERIC, OR1200_RFRAM_TWOPORT or OR1200_RFRAM_DUALPORT) (dual port is supported by Xilinx BRAM and Altera)
      (select only one of the three)
      if Altera: include `define OR1200_ALTERA_LPM_XXX (right under `define OR1200_ALTERA_LPM if you wish).
    3. comment `define OR1200_QMEM_IMPLEMENTED
    4. comment `define OR1200_PM_IMPLEMENTED
    5. If not using Linux you can:
      • uncomment `define OR1200_NO_DC
      • uncomment `define OR1200_NO_IC
      • uncomment `define OR1200_NO_DMMU
      • uncomment `define OR1200_NO_IMMU
      • comment out `define OR1200_CFGR_IMPLEMENTED
    6. If you don't need multiplication, mac operations or divisions
      • comment out `define OR1200_MULT_IMPLEMENTED
      • comment out `define OR1200_MAC_IMPLEMENTED
      • comment out `define OR1200_DIV_IMPLEMENTED
        (If you do this, change sw/support/Makefile.inc line 7: GCC_OPT=-mhard-mul -g -nostdlib to GCC_OPT=-msoft-mul -msoft-div -g -nostdlib)

While running UART firmware example on my FPGA, the data shown by my computer's terminal are weird characters instead of "Hello World!".

Answer: A specific problem with the frequency 12.5 MHz has been noticed, for which the SoC delivers weird characters on the terminal output.

This has been detected as an error caused by a truncation operation.

The system baudrate is configured by a register in the uart module from the SoC. The formula is:

value = sys_clk/(16*desired_baud_rate)

For 25MHz system clock this is 13.56. Truncating to 13, it leads to a real baudrate of 120,192.3 bps. For 12.5MHz system clock this is 6.78. Truncating to 6, it leads to a real baudrate of 130,208.3 bps.

This skew to the computer's baudrate of 115,200 is responsible for the weird characteres. If you round it up to 7 you get a real baudrate of 111,607.14 which happens to work.

That truncation is executed by the file sw/drivers/uart.c line 45. If you remove the calculation and directly type in the rounded value, 7 here, it will work flawlessly.

I know this happens to be a somewhat obvious. But since the system is hiding the baudrate configuration from the user, by calculating it directly from system clock and desired baudrate inputs, it is important to make clear that these things might show up, and that this is the way to get rid of these errors.

Tweaks

I want my design to automatically initialize my firmware on power-up, how do I do that?

Answer: Nowadays there are 3 options to do that:

  1. MinSoC comprehends the standard of them which is based on the project OR1k Start-up from OpenCores. At system power-up the CPU's program counter is jumped to the OR1k Start-up module by a Start-up Starter module (inside of minsoc_top.v). The OR1k Start-up contains a hardwired code which reads the data from a SPI memory and copy it to main memory. The amount of data copied is decided upon reading of the first 32 bits of the SPI memory, which must contain the firmware's size. After the code has been completely copied, it restarts the CPU.

    To use this, all you have to do is uncomment “`define START_UP” from “minsoc_defines.v”. Don't forget to load the hex file created by the project's Makefiles into the SPI memory, so actually your firmware is copied to the main memory. The hex file is created from the or32 executable by the project's existing Makefiles.

    Everytime the firmware is updated it has to be uploaded to the SPI memory. You can read about it in more detail in the minsoc.pdf file chapter 2.3 Start-Up Modules.

    Advantages: works with any memory type. The speed will be the speed needed by the memory programmer to program the external SPI memory. After that you press the reset button and the firmware will be loaded from the SPI memory by the system. It will then be run.
    Drawback: no debugging, somewhat bigger SoC, required onboard SPI flash.
  2. A Xilinx approach has been implemented by Ravi Kumar. A similar Altera approach has been implemented by “sotusotu”. This approach creates a memory initialization file off the firmware executable file, which is then linked to “minsoc_onchip_ram_top.v”.

    Everytime the firmware is changed the synthesizer and P&R must be run for the SoC.

    Link Xilinx: http://opencores.org/forum,OpenRISC,0,3628,0 post 9.
    Link Altera: http://opencores.org/forum,OpenRISC,0,3749 post 5.

    Advantages: once you have a target firmware, it will be on RAM right after FPGA configuration.
    Drawbacks: you have to re-synthesize, re-place&Route to create the bitfile with the firmware, no debugging, only works with onchip-RAM.
  3. The XSOC project has yet another approach to pre-initialize the memory with a firmware. They have created a Perl script, that update the SoC resulting bitfile substituting the memory initialization with the target firmware.

    The difference to approach 2 is that approach 2 requires new run of the synthesizer & P&R in order to exchange the firmware, while this directly updates the bitfile result of that very process. After that only a FPGA configuration is necessary to have the new firmware.

    Link: http://pm.stu.cn.ua/wiki/10/Getting_started “Updating bitstream with new software”

    Advantages: high speed,on RAM right after FPGA configuration.\
    Drawbacks: no debugging, only works with onchip-RAM.

I want to compile my firmware independent of MinSoC library but it does not work, what am I doing wrong?

Short example: user “ag1986” says: “test.c

#include stdio.h
int main()
{int a,b,c;
a=5;b=10;
c=a+b;
}

Binary generation: “or32-elf-gcc test.c -o test.or32” Simulating using “or1k-sim: or32-elf-sim -f sim.cfg –enable-profile test.or32” does not work.”

Answer: You need a “bootloader” in order to make your software work.

I will try to clearly explain its task in the following lines by comparing it to you running a program on your own operating system.

When you type in the “linux shell” “ls” or “dir” in “windows command prompt”, the operating system creates a new process for this program; set a runnable environment for it, with stack, registers and memory; and then at some point set the program counter to the start of your program. (http://en.wikipedia.org/wiki/Process_fork).

The key points here are, you are creating a binary which:

  • does not have any information about position in memory
  • you are not initializing a stack
  • you are not initializing registers
  • you are not saying how much memory is available

And without these, your software will simply not work. For instance, if your binary will be located starting at address 0x00, your software will not be ever executed from the beginning by the OpenRISC since it resets to 0x100 and go then onwards until memory finishes.

So, how do I solve this? Generally you cannot directly set registers in C, so you actually need sort of a C assembly mix and then link them together. Furthermore a linker script is used to create memory spaces so you can actually organize the memory dividing data from instruction, exceptions from code and so on.

You find an explanation to bootstrapping firmwares in the 5th post on this thread and a small Makefile project with a bootloader in the link under the post.

Note: you find more about this in minsoc.pdf chapter 3.1 Bootstrapping: a tiny bootloader.

How to include a 8 bit module to the SoC?

Answer: Modules are connected to the Wishbone 32 bit interconnect, to which all SoC modules are connected and can thus communicate. If you want to connect an 8 bit module to the 32 bit interconnect you need a bridge, which resolves the non-aligned memory accesses to the right address and forwards the right Byte data to the 8 bits on the other end. To do so, you need to connect the module “minsoc_wb_32_8_bridge” to the interconnect and the 8 bit module on the other end. The module “minsoc_wb_32_8_bridge” can be found under “minsoc/utils/”.

Once the hardware is ready, you have to take special care while programing your firmware not to issue 32 bit accesses to an 8 bit module. That can be easily done by using the right macros to do so:

#define REG8(add) *((volatile unsigned char *)(add))
#define REG16(add) *((volatile unsigned short *)(add))
#define REG32(add) *((volatile unsigned long *)(add))

These macros are found in the provided support library (“minsoc/sw/support/support.h”) To access 8 bit modules, use only REG8. That assures that the instruction l.sb is used and not l.sw. The former stores a byte, while the latter a word. For more information about how to include new modules to the system, please refer to “doc/minsoc.pdf” “2.2.2 Attaching Modules to the System”.

Related discussion: http://opencores.org/forum,OpenRISC,0,3552

1) If you have INITIALIZE_MEMORY_MODEL enabled or you have START_UP and waited for the message: “Memory start-up completed…” don't need to run load
minsoc_faq.txt · Last modified: 2012/02/01 11:03 by maiden