mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
120 lines
3.4 KiB
Python
120 lines
3.4 KiB
Python
from math import atan, sqrt, ceil, floor, pi
|
|
|
|
from myhdl import *
|
|
|
|
t_State = enum("WAITING", "CALCULATING")
|
|
|
|
def SineComputer(cos_z0, sin_z0, done, z0, start, clock, reset):
|
|
|
|
""" Sine and cosine computer.
|
|
|
|
This module computes the sine and cosine of an input angle. The
|
|
floating point numbers are represented as integers by scaling them
|
|
up with a factor corresponding to the number of bits after the point.
|
|
|
|
Ports:
|
|
-----
|
|
cos_z0: cosine of the input angle
|
|
sin_z0: sine of the input angle
|
|
done: output flag indicated completion of the computation
|
|
z0: input angle; -pi/2 <= z0 <= pi/2
|
|
start: input that starts the computation on a posedge
|
|
clock: clock input
|
|
reset: reset input
|
|
|
|
"""
|
|
|
|
# angle input bit width
|
|
W = len(z0)
|
|
|
|
# angle input z0 represents number between -pi/2 and pi/2
|
|
# scaling factor corresponds to the nr of bits after the point
|
|
M = 2 ** (W-2)
|
|
|
|
# nr of iterations equals nr of significant input bits
|
|
N = W-1
|
|
|
|
# calculate X0
|
|
An = 1.0
|
|
for i in range(N):
|
|
An *= (sqrt(1 + 2**(-2*i)))
|
|
|
|
# X0
|
|
X0 = int(round(M*1/An))
|
|
|
|
# tuple with elementary angles
|
|
angles = tuple([int(round(M*atan(2**(-i)))) for i in range(N)])
|
|
|
|
# iterative cordic processor
|
|
@instance
|
|
def processor():
|
|
|
|
x = intbv(0, min=sin_z0.min, max=sin_z0.max)
|
|
y = intbv(0, min=sin_z0.min, max=sin_z0.max)
|
|
z = intbv(0, min=z0.min, max=z0.max)
|
|
dx = intbv(0, min=sin_z0.min, max=sin_z0.max)
|
|
dy = intbv(0, min=sin_z0.min, max=sin_z0.max)
|
|
dz = intbv(0, min=z0.min, max=z0.max)
|
|
i = intbv(0, min=0, max=N)
|
|
state = t_State.WAITING
|
|
|
|
while True:
|
|
yield clock.posedge, reset.posedge
|
|
|
|
if reset:
|
|
state = t_State.WAITING
|
|
cos_z0.next = 1
|
|
sin_z0.next = 0
|
|
done.next = False
|
|
x[:] = 0
|
|
y[:] = 0
|
|
z[:] = 0
|
|
i[:] = 0
|
|
|
|
else:
|
|
if state == t_State.WAITING:
|
|
if start:
|
|
x[:] = X0
|
|
y[:] = 0
|
|
z[:] = z0
|
|
i[:] = 0
|
|
done.next = False
|
|
state = t_State.CALCULATING
|
|
|
|
elif state == t_State.CALCULATING:
|
|
dx[:] = y >> i
|
|
dy[:] = x >> i
|
|
dz[:] = angles[int(i)]
|
|
if (z >= 0):
|
|
x -= dx
|
|
y += dy
|
|
z -= dz
|
|
else:
|
|
x += dx
|
|
y -= dy
|
|
z += dz
|
|
if i == N-1:
|
|
cos_z0.next = x
|
|
sin_z0.next = y
|
|
state = t_State.WAITING
|
|
done.next = True
|
|
else:
|
|
i += 1
|
|
|
|
return processor
|
|
|
|
def SineComputer_v(cos_z0, sin_z0, done, z0, start, clock, reset):
|
|
toVerilog(SineComputer, cos_z0, sin_z0, done, z0, start, clock, reset)
|
|
cmd = "cver -q +loadvpi=myhdl_vpi:vpi_compat_bootstrap " + \
|
|
"SineComputer.v tb_SineComputer.v"
|
|
return Cosimulation(cmd, **locals())
|
|
## cmd = "iverilog SineComputer.v tb_SineComputer.v"
|
|
## import os
|
|
## os.system(cmd)
|
|
## return Cosimulation("vvp -m ./myhdl.vpi a.out", **locals())
|
|
|
|
|
|
|
|
|
|
|