1 from nmigen
import Module
, Elaboratable
, Signal
, Memory
, signed
2 from nmigen
.cli
import rtlil
4 from enum
import Enum
, unique
8 class CordicState(Enum
):
13 class CordicROM(Elaboratable
):
14 def __init__(self
, fracbits
, iterations
):
15 self
.fracbits
= fracbits
16 self
.iterations
= iterations
19 self
.addr
= Signal(range(iterations
))
20 self
.data
= Signal(range(-M
, M
-1))
22 angles
= [int(round(M
*math
.atan(2**(-i
))))
23 for i
in range(self
.iterations
)]
25 self
.mem
= Memory(width
=self
.data
.width
,
26 depth
=self
.iterations
,
29 def elaborate(self
, platform
):
31 m
.submodules
.rdport
= rdport
= self
.mem
.read_port()
32 m
.d
.comb
+= rdport
.addr
.eq(self
.addr
)
33 m
.d
.comb
+= self
.data
.eq(rdport
.data
)
37 class CORDIC(Elaboratable
):
38 def __init__(self
, fracbits
):
39 self
.fracbits
= fracbits
40 self
.M
= M
= (1 << fracbits
)
41 self
.ZMAX
= ZMAX
= int(round(self
.M
* math
.pi
/2))
43 # sin/cos output in 0.ffffff format
44 self
.cos
= Signal(range(-M
, M
-1), reset
=0)
45 self
.sin
= Signal(range(-M
, M
-1), reset
=0)
47 self
.z0
= Signal(range(-ZMAX
, ZMAX
), reset_less
=True)
50 self
.start
= Signal(reset_less
=True)
51 # cordic done/ready for input
52 self
.ready
= Signal(reset
=True)
54 self
.width
= self
.z0
.width
55 self
.iterations
= self
.width
- 1
57 def elaborate(self
, platform
):
63 # Calculate initial amplitude?
65 for i
in range(self
.iterations
):
66 An
*= math
.sqrt(1 + 2**(-2*i
))
68 X0
= int(round(self
.M
*1/An
))
69 x
= Signal(self
.sin
.shape())
70 y
= Signal(self
.sin
.shape())
71 z
= Signal(self
.z0
.shape())
72 dx
= Signal(self
.sin
.shape())
73 dy
= Signal(self
.sin
.shape())
74 dz
= Signal(self
.z0
.shape())
75 i
= Signal(range(self
.iterations
))
76 state
= Signal(CordicState
, reset
=CordicState
.WAITING
)
78 m
.submodules
.anglerom
= anglerom
= \
79 CordicROM(self
.fracbits
, self
.iterations
)
83 comb
+= dz
.eq(anglerom
.data
)
84 comb
+= self
.cos
.eq(x
)
85 comb
+= self
.sin
.eq(y
)
86 with m
.If(state
== CordicState
.WAITING
):
87 with m
.If(self
.start
):
92 sync
+= self
.ready
.eq(0)
93 sync
+= state
.eq(CordicState
.RUNNING
)
94 sync
+= anglerom
.addr
.eq(1)
95 with m
.If(state
== CordicState
.RUNNING
):
104 with m
.If(i
== self
.iterations
- 1):
105 sync
+= state
.eq(CordicState
.WAITING
)
106 sync
+= self
.ready
.eq(1)
109 sync
+= anglerom
.addr
.eq(i
+2)
113 return [self
.cos
, self
.sin
, self
.z0
,
114 self
.ready
, self
.start
]
116 if __name__
== '__main__':
118 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
119 with
open("cordic.il", "w") as f
: