Search code examples
pythonvhdlmyhdl

MyHDL VHDL conversion: no index value can belong to null index range


For an algorithm I implemented and successfully converted to VHDL, I get this error during the "Static elaboration of top level VHDL design":

no index value can belong to null index range

I boiled the code down to the essential part (you might recognize a cordic processor).

import myhdl
from myhdl import enum, intbv, always_comb, always_seq, always, instance, Signal, ResetSignal, Simulation, delay, StopSimulation
import unittest
from unittest import TestCase


# input bit width
BIT_IN = 16

########################################################
#                  IMPLEMENTATION                      #
########################################################

def NullIndex(clk, reset):

  R2P_W = 16

  # nr of iterations equals nr of significant input bits
  R2P_N = R2P_W-1

  R2P_LIMIT = 2**(R2P_W+1)

  x = [Signal(intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT)) for _ in range(R2P_N+1)]
  y = [Signal(intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT)) for _ in range(R2P_N+1)]
  z = [Signal(intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT)) for _ in range(R2P_N+1)]

  @always_seq(clk.posedge, reset=reset)
  def processor():
      dx = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
      dy = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
      dz = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]

      # actual algorithm
      # starting vector
      x[0].next = 42
      y[0].next = 42
      z[0].next = 0

      # connect all stages of the pipeline where stage 1 has been defined by the starting conditions above
      for i in range(0, R2P_N):
          # shifting performs the 2**(-i) operation
          dx[i+1][:] = x[i] >> i
          dy[i+1][:] = y[i] >> i
          dz[i+1][:] = 42 #don't worry, normally not a constant
          if (y[i] > 0):
              x[i+1].next = x[i] + dy[i+1]
              y[i+1].next = y[i] - dx[i+1]
              z[i+1].next = z[i] + dz[i+1]
          else:
              x[i+1].next = x[i] - dy[i+1]
              y[i+1].next = y[i] + dx[i+1]
              z[i+1].next = z[i] - dz[i+1]

  return processor



########################################################
#                      TESTS                           #
########################################################

class TestNullIndex(TestCase):

    def setUp(self):
        # input/output width
        self.m = BIT_IN
        self.limit = 2**self.m

        # signals
        self.clk = Signal(bool(0))
        self.reset = ResetSignal(0, active=1, async=True)


    def testDut(self):    
        # actual test
        def test(clk):
          for _ in range(42):
            yield clk.posedge

          raise StopSimulation

        # instances
        dut = myhdl.toVHDL( NullIndex, clk=self.clk, reset=self.reset )
        inst_test = test(self.clk)

        # clock generator
        @always(delay(1))
        def clkGen():
          self.clk.next = not self.clk

        sim = Simulation(clkGen, dut, inst_test)
        sim.run(quiet=1)




if __name__ == "__main__":
  unittest.main()

The intereseting part is

dx = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
.
.

When converted to VHDL it will spit out something like that for the d[x,y,z] arrays:

type t_array_dz is array(0 to -1-1) of signed(17 downto 0);
variable dz: t_array_dz;
type t_array_dx is array(0 to -1-1) of signed(17 downto 0);
variable dx: t_array_dx;
type t_array_dy is array(0 to -1-1) of signed(17 downto 0);
variable dy: t_array_dy;

which will eventually result in the error since the array can't be from 0 to -1-1. Why does this happen and what did I wrong?


Solution

  • For variables declarations, MyHDL does not seem to support having an expression in the call to range in the list comprehension (although it does for signal declarations).

    If you change this:

    dx = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
    dy = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
    dz = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(R2P_N+1)]
    

    to this:

    dx = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(16)]
    dy = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(16)]
    dz = [intbv(0, min=-R2P_LIMIT, max=R2P_LIMIT) for _ in range(16)]
    

    Then you get the expected VHDL declarations:

    type t_array_dz is array(0 to 16-1) of signed(17 downto 0);
    variable dz: t_array_dz;
    type t_array_dx is array(0 to 16-1) of signed(17 downto 0);
    variable dx: t_array_dx;
    type t_array_dy is array(0 to 16-1) of signed(17 downto 0);
    variable dy: t_array_dy;