Thanks. One not to give up, pinged their tech support and had a 1 hour chat online with their FAE and sales head. This is very positive in our books.
The developers for this line appear to be overseas but still appreciate their efforts to assist. In the end, more caffeine led to the resolution.
Summary...their example in our opinion is very poorly documented and is also broken for the APB3Slave that we wish to deploy on this 32 bit SOC (RISC-V CPU). As we are rather new to Verilog and certainly new to this component, the toolchain and the RISC-V CPU...many hurdles slowing us down. It is not our first rodeo (actually never been to one) but would welcome a vendor that has 100% accurate examples; documentation and quick support when we are stuck. Should not take days upon days of trial & error to fix the vendor's products.
Happy to say that after days of efforts, have the understanding of the APB3Slave IP. For any future reader and developer of this T8 OPAL SOC, here is a simple (fixed) 'C' code for the SOC that is working.
The current documentation claims that the example 'C' code will do a memory write and read but we do not see this in the posted example. More so, 'assumed' that the APB3Slave was the one performing the LED blinking - that was our wrong assumption. Killed too many brain cells in compiling the APB3Slave verilog file in an attempt to halt the LEDs from blinking. Every attempt was a failure. It was the code from h*ll and kept flashing. In the end, the LED blink logic is not linked to the APB3Slave bus at all. Sad example to learn from.
The corrected code is copied below:
#include "C:\riscv-sdk\SDK_Windows\riscv-xpack-toolchain_8.3.0-1.1_windows\riscv-none-embed\include\stdint.h"
#include "C:\Efinity\Projects\RiscV\Xyloni\soc_opal_t8\soc_Opal_sw_t8\bsp\efinix\EfxOpalSoc\include\bsp.h"
#include "C:\Efinity\Projects\RiscV\Xyloni\soc_opal_t8\soc_Opal_sw_t8\software\standalone\driver\gpio.h"
#include "C:\Efinity\Projects\RiscV\Xyloni\soc_opal_t8\soc_Opal_sw_t8\software\standalone\driver\uart.h"
#include "C:\Efinity\Projects\RiscV\Xyloni\soc_opal_t8\soc_Opal_sw_t8\software\standalone\driver\apb3_cl.h"
#ifdef SPINAL_SIM
#define LOOP_UDELAY 100
#else
#define LOOP_UDELAY 100000
#endif
// This code example will first WRITE to APB3 Slave register # 0 (32 bit value)
// then READ back from register # 0 of the APB3 Slave
//
// if the READ value matches the WRITE value, the LEDs will blink, else will NOT blink
//
void main() {
u32 val;
struct example_apb3_ctrl_reg cfg={0};
bsp_init();
gpio_setOutputEnable(BSP_LED_GPIO, BSP_LED_MASK);
gpio_setOutput(BSP_LED_GPIO, 0x00000000);
uart_writeStr(BSP_UART_TERMINAL, "(fixed) Opal Soc T8: Example Design\n\r");
// write the bit pattern for 0x0000 0000 0000 0002 to the APB3 Slave register #0
cfg.exampleLED1 = 0;
cfg.exampleLED2 = 1;
example_register_write(&cfg); // write the 32 bit value to the APB3 Slave peripheral
// prepare the LEDs for blinking
gpio_setOutput(BSP_LED_GPIO, gpio_getOutput(BSP_LED_GPIO) ^ BSP_LED_MASK);
while(1){
//gpio_setOutput(BSP_LED_GPIO, gpio_getOutput(BSP_LED_GPIO) ^ BSP_LED_MASK);
//cfg.exampleLED1 = ~cfg.exampleLED1;
//cfg.exampleLED2 = ~cfg.exampleLED2;
//example_register_write(&cfg);
// READ back the 32 bit value from the APB3 Slave peripheral
val = example_register_read();
bsp_uDelay(LOOP_UDELAY);
// blink the LEDs only if the RTL slave code returns a value that was written above
// from register # 0
if (val == 0x0000000000000002)
gpio_setOutput(BSP_LED_GPIO, gpio_getOutput(BSP_LED_GPIO) ^ BSP_LED_MASK);
}
}
#ifndef APB3_CL_H
#define APB3_CL_H
#include "bsp.h"
#define EXAMPLE_APB3_SLV IO_APB_SLAVE_0_APB
#define EXAMPLE_APB3_SLV_REG0_OFFSET 0
#define EXAMPLE_APB3_SLV_REG1_OFFSET 4
#define EXAMPLE_APB3_REGW(addr, offset, data) \
write_u32(data, addr+offset)
#define EXAMPLE_APB3_REGR(addr, offset) \
read_u32(addr+offset)
struct example_apb3_ctrl_reg {
unsigned int exampleLED1 :1;
unsigned int exampleLED2 :1;
unsigned int exampleInterrupt :1;
unsigned int exampleReserved :29;
}example_apb3_ctrl_reg;
u32 example_register_read()
{
u32 rdata;
rdata = EXAMPLE_APB3_REGR(EXAMPLE_APB3_SLV, EXAMPLE_APB3_SLV_REG0_OFFSET);
return rdata;
}
void example_register_write(struct example_apb3_ctrl_reg *cfg)
{
EXAMPLE_APB3_REGW(EXAMPLE_APB3_SLV, EXAMPLE_APB3_SLV_REG0_OFFSET, *(int *)cfg );
}
void example_register_write(struct example_apb3_ctrl_reg *cfg);
u32 example_register_read();
#endif
Guessing in the future, these errors will be corrected. I know that we have reported countless errors in the documentation and example issues with Lattice which still need to reach their website. These rather large suppliers are after the big fish and should not ignore the smaller guys. A story we have repeated many times over the years...had a similar support case with a 'no-name client' at the time who bombarded us with technical issues / questions on one of our products for 3-4 business days. We replied to each one promptly. The client that revealed themselves as HP. We have had that OEM account for the past 20 years and counting...