HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Click here to toggle on/off the raw code."></form>''')
import matplotlib.pyplot as plt
from IPython.display import HTML
plt.rcParams["figure.figsize"] = (20,3)
import numpy
For this laboratory exercise, you will be asked to build a Digital Differential Analyzer (DDA) in Verilog that integrates the Lorenz system. The Lorenz system generates (arguably) one of the most famous and beautiful structures in mathematics: the "butterfly curve" (from which the "butterfly effect" gets its name). For certain parameter values and initial conditions, the solutions for the Lorenz system are chaotic. That is to say, they are deterministic yet unpredictable. The solutions are so sensitive to initial conditions that, after sufficient time, it is no longer possible to determine the path that the system will take without running a simulation. Meditate on the notion of "deterministic yet unpredictable" for long enough and you may end up questioning things like your own free will. But I digress.
The DDA circuit that you build will be controlled by the HPS. Controlling the DDA involves clocking it and setting initial conditions/parameter values. You will build a system that allows for you to play with the Lorenz system. The VGA screen will display all three projections of the 3D curve, and your user interface will support speeding up/slowing down animation, pausing/resuming animation, clearing the screen, dynamically changing parameters, and resetting with a new set of user-specified initial conditions.
Finally, you will implement three Direct Digital Synthesis synthesizers in Verilog that independently generate three tones from a speaker. Those tones will be functions of the x, y, and z state variable values, and will allow for us to listen to this chaotic system. This is all demonstrated in the video below.
The Lorenz system is described by a set of three coupled ordinary differential equations, given below:
You will numerically integrate these differential equations using the Euler method, the simplest of all numerical integration techniques. The Euler method linearizes about the values of the state variables $x$, $y$, and $z$ at the current timestep to approximate the values of the state variables at the next timestep. That is:
Starting this iteration requires initial values for $x$, $y$, and $z$ and parameter values for $\sigma$, $\beta$, $\rho$, and $dt$. Ultimately, your system will accept arbitrary initial conditions and parameter values. However, use the following as the default settings:
The Python code below provides a reference solution to which you may compare your solutions. But remember that your solutions will not match exactly because the system is chaotic. One of the first steps for this lab is to simulate the solver in hardware in ModelSim to produce something like the following curves. For your amusement, here is an interactive 3D plot of the Lorenz system.
dt = (1./256)
x = [-1.]
y = [0.1]
z = [25.]
sigma = 10.0
beta = 8./3.
rho = 28.0
def dx(sigma, x, y):
return sigma*(y-x)
def dy(rho, x, y, z):
return x*(rho-z)-y
def dz(beta, x, y, z):
return x*y - beta*z
for i in range(10000):
x.extend([x[i] + dt*dx(sigma, x[i], y[i])])
y.extend([y[i] + dt*dy(rho, x[i], y[i], z[i])])
z.extend([z[i] + dt*dz(beta, x[i], y[i], z[i])])
dt = (1./256)
x = [-1.]
y = [0.1]
z = [25.]
sigma = 10.0
beta = 8./3.
rho = 28.0
def dx(sigma, x, y):
return sigma*(y-x)
def dy(rho, x, y, z):
return x*(rho-z)-y
def dz(beta, x, y, z):
return x*y - beta*z
for i in range(10000):
x.extend([x[i] + dt*dx(sigma, x[i], y[i])])
y.extend([y[i] + dt*dy(rho, x[i], y[i], z[i])])
z.extend([z[i] + dt*dz(beta, x[i], y[i], z[i])])
plt.plot(x)
plt.ylabel('X', fontsize=18)
plt.show()
plt.plot(y)
plt.ylabel('Y', fontsize=18)
plt.show()
plt.plot(z)
plt.ylabel('Z', fontsize=18)
plt.ylim([-10, 50])
plt.show()
# import plotly.graph_objects as go
# fig = go.Figure(data=go.Scatter3d(x=x,
# y=y,
# z=z,
# mode='markers',
# marker=dict(
# size=2)))
# fig.write_html("./test.html")
# fig.show()
You will be asked to implement the above Euler integrator in hardware using Verilog. The circuit that you will build is illustrated below.
For most exercises there will be 5 or six connections to the board: serial, ethernet, VGA, audio (for lab 2), USB blaster, power. See the image below.
You will find the following resources useful:
details>datasheet
. Some other modules require that you follow the path details>open_component_folder
to get the datasheet.module freq_LUT (
input wire [5:0] address,
output wire [31:0] dds_increment_out
) ;
reg [31:0] dds_increment ;
always@(address)
begin
case(address)
6'd0: dds_increment=32'd2460658;
6'd1: dds_increment=32'd2762200;
6'd2: dds_increment=32'd2925946;
6'd3: dds_increment=32'd3284755;
6'd4: dds_increment=32'd3686513;
6'd5: dds_increment=32'd3905735;
6'd6: dds_increment=32'd4384445;
6'd7: dds_increment=32'd4921316;
6'd8: dds_increment=32'd5524401;
6'd9: dds_increment=32'd5852787;
6'd10: dds_increment=32'd6569510;
6'd11: dds_increment=32'd7373921;
6'd12: dds_increment=32'd7812366;
6'd13: dds_increment=32'd8768891;
6'd14: dds_increment=32'd9842633;
6'd15: dds_increment=32'd11047908;
6'd16: dds_increment=32'd11704680;
6'd17: dds_increment=32'd13138126;
6'd18: dds_increment=32'd14746949;
6'd19: dds_increment=32'd15623838;
6'd20: dds_increment=32'd17537783;
6'd21: dds_increment=32'd19685266;
6'd22: dds_increment=32'd22095817;
6'd23: dds_increment=32'd23410256;
6'd24: dds_increment=32'd26276252;
6'd25: dds_increment=32'd29494793;
6'd26: dds_increment=32'd31248571;
6'd27: dds_increment=32'd35075566;
6'd28: dds_increment=32'd39370533;
6'd29: dds_increment=32'd44191634;
6'd30: dds_increment=32'd46819617;
6'd31: dds_increment=32'd52553398;
6'd32: dds_increment=32'd58988691;
6'd33: dds_increment=32'd62497142;
6'd34: dds_increment=32'd70150237;
6'd35: dds_increment=32'd78741067;
6'd36: dds_increment=32'd88384163;
6'd37: dds_increment=32'd93639234;
6'd38: dds_increment=32'd105106797;
6'd39: dds_increment=32'd117978277;
6'd40: dds_increment=32'd124993390;
6'd41: dds_increment=32'd140300475;
6'd42: dds_increment=32'd157482134;
6'd43: dds_increment=32'd176767432;
6'd44: dds_increment=32'd187278469;
6'd45: dds_increment=32'd210213595;
6'd46: dds_increment=32'd235956555;
6'd47: dds_increment=32'd249987676;
6'd48: dds_increment=32'd280600950;
6'd49: dds_increment=32'd314964268;
6'd50: dds_increment=32'd353535759;
6'd51: dds_increment=32'd374557834;
default dds_increment =32'd0 ;
endcase
end
assign dds_increment_out = dds_increment ;
endmodule
Your lab reports should include: