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?
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;