I'm designing a Qsys component which I want to be user-configurable. It has config parameters which are defined in the TCL file. For example, for a GPIO bank component I would write:

add_parameter GPIO_OUTPUTS_COUNT POSITIVE 8 "Number of GPIO pins"
set_parameter_property GPIO_OUTPUTS_COUNT DEFAULT_VALUE 8
set_parameter_property GPIO_OUTPUTS_COUNT ALLOWED_RANGES 1:32
set_parameter_property GPIO_OUTPUTS_COUNT HDL_PARAMETER true

The value of this parameter can be accesses in HDL code easily:

module gpio

parameter GPIO_OUTPUTS_COUNT; // gets the value assigned by user

Now, I would also like to have this value in my driver's C code, e.g. to check for errors where the user is trying to access non-existing pins:

int gpio_write(pin, level) {
    if(pin >= GPIO_OUTPUTS_COUNT) return -1; // No such pin


    return 0; // Success

How can I get GPIO_OUTPUTS_COUNT name defined in my C code?


Several ways spring to mind:

A/ The way I have done this in the past is to add the parameters to the registers.

A (professional) peripheral has:

  • An ID register
  • A version register

I have added to that:

  • Parameter register.

If required you can easily pack four 8-bit parameters in a 32-bit register:

case (read_adrs)
4'h0 : rdata <= control_register;
4'h4 : rdata <= 32'h4F495047; // "GPIO" in little endian
4'hC : rdata <= GPIO_OUTPUTS_COUNT;

The CPU can then read the width. The disadvantage is that with a define you can have all compile-time optimizations which are now not possible.

B/ As an alternative to put all that type of parameters in one include file. Then you could make a sed script which converts the Verilog 'include file' format to C include file format and include that. The syntax is close enough to make that very simple.

C/ Add a define to both make files. But I find that error prone.

  • \$\begingroup\$ I thought about exposing all HDL settings in the address space, but like you mention, this excludes any chance of setting-specific compiler optimization. \$\endgroup\$ – Dmitry Grigoryev Jun 16 '19 at 14:19

Adding the following contraption to the TCL file worked:

set_module_property VALIDATION_CALLBACK validate
proc validate {} {
    set GPIO_OUTPUTS_COUNT [ get_parameter_value GPIO_OUTPUTS_COUNT ]
    set_module_assignment embeddedsw.CMacro.OUTPUTS_COUNT "$GPIO_OUTPUTS_COUNT"

Assuming the component instance is called gpio_0, the following line will be added to system.h upon generation:

#define GPIO_0_OUTPUTS_COUNT 8 // Value selected by the user in Qsys

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.