z output reading
This commit is contained in:
parent
1a97dfa5aa
commit
8b8e14bc7f
|
@ -0,0 +1,26 @@
|
||||||
|
"""
|
||||||
|
Copyright 2023 (C) Peter McGoron
|
||||||
|
|
||||||
|
This file is a part of Upsilon, a free and open source software project.
|
||||||
|
For license terms, refer to the files in `doc/copying` in the Upsilon
|
||||||
|
source distribution.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import pandas as pd
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
|
from util import *
|
||||||
|
|
||||||
|
Pval = string_to_fixed_point('0.0006', 43)
|
||||||
|
Ival = string_to_fixed_point('0.01', 43)
|
||||||
|
|
||||||
|
out = connect_execute("control_loop_test.py", Pval, Ival, 10000, 100)
|
||||||
|
|
||||||
|
################
|
||||||
|
# Script Handler
|
||||||
|
################
|
||||||
|
|
||||||
|
for line in out.stdout:
|
||||||
|
print(line)
|
|
@ -0,0 +1,107 @@
|
||||||
|
"""
|
||||||
|
Copyright 2023 (C) Peter McGoron
|
||||||
|
|
||||||
|
This file is a part of Upsilon, a free and open source software project.
|
||||||
|
For license terms, refer to the files in `doc/copying` in the Upsilon
|
||||||
|
source distribution.
|
||||||
|
"""
|
||||||
|
from math import log10, floor
|
||||||
|
from decimal import *
|
||||||
|
|
||||||
|
def sign_extend(value, bits):
|
||||||
|
"""
|
||||||
|
Interpret ``value`` as a twos-complement integer of ``bits`` length.
|
||||||
|
|
||||||
|
:param value: Twos-complement integer with finite bit width.
|
||||||
|
:param bits: Bit length of ``value``.
|
||||||
|
:return: ``value`` converted to a Python integer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check the sign bit of the integer.
|
||||||
|
is_signed = (value >> (bits - 1)) & 1 == 1
|
||||||
|
# If not signed, just return the integer.
|
||||||
|
if not is_signed:
|
||||||
|
return value
|
||||||
|
# Otherwise,
|
||||||
|
# 1. Do an explicit twos-complement negation
|
||||||
|
# 2. Mask all the non-sign bits
|
||||||
|
# This returns the positive value as a standard Python integer.
|
||||||
|
# Then the function negates the positive integer to get the negative
|
||||||
|
# one back.
|
||||||
|
return -((~value + 1) & ((1 << (bits - 1)) - 1))
|
||||||
|
|
||||||
|
def connect_execute(f, *arg):
|
||||||
|
from pssh.clients import SSHClient # require parallel-ssh
|
||||||
|
|
||||||
|
print('connecting')
|
||||||
|
client = SSHClient('192.168.1.50', user='root', pkey='~/.ssh/upsilon_key')
|
||||||
|
# Upload the script.
|
||||||
|
print('connected')
|
||||||
|
client.scp_send(f'../linux/{f}', '/root/')
|
||||||
|
# Run the script.
|
||||||
|
args = f'micropython {f} {" ".join([str(s) for s in arg])}'
|
||||||
|
print(f"running {args}")
|
||||||
|
return client.run_command(args)
|
||||||
|
|
||||||
|
# Functions for converting to and from fixed point in Python.
|
||||||
|
|
||||||
|
def string_to_fixed_point(s, fracnum):
|
||||||
|
l = s.split('.')
|
||||||
|
if len(l) == 1:
|
||||||
|
return int(s) << fracnum
|
||||||
|
elif len(l) != 2:
|
||||||
|
return None
|
||||||
|
|
||||||
|
dec = 10
|
||||||
|
frac = 0
|
||||||
|
|
||||||
|
frac_decimal = Decimal(f'0.{l[1]}')
|
||||||
|
# get the smallest power of ten higher then frac_decimal
|
||||||
|
frac = 0
|
||||||
|
|
||||||
|
# Example:
|
||||||
|
# 0.4567 = 0.abcdefgh...
|
||||||
|
# where abcdefgh are binary digits.
|
||||||
|
# multiply both sides by two:
|
||||||
|
# 0.9134 = a.bcdefgh ...
|
||||||
|
# therefore a = 0. Then remove the most significant digit.
|
||||||
|
# Then multiply by 2 again. Then
|
||||||
|
# 1.8268 = b.cdefgh ...
|
||||||
|
# therefore b = 1. Then take 8268, and so on.
|
||||||
|
for i in range(0,fracnum):
|
||||||
|
frac_decimal = frac_decimal * 2
|
||||||
|
div = floor(frac_decimal)
|
||||||
|
|
||||||
|
frac = div | (frac << 1)
|
||||||
|
frac_decimal = frac_decimal - div
|
||||||
|
|
||||||
|
whole = int(l[0])
|
||||||
|
if whole < 0:
|
||||||
|
return -((-whole) << fracnum | frac)
|
||||||
|
else:
|
||||||
|
return whole << fracnum | frac
|
||||||
|
|
||||||
|
def fixed_point_to_string(fxp, fracnum):
|
||||||
|
whole = str(fxp >> fracnum)
|
||||||
|
mask = (1 << fracnum) - 1
|
||||||
|
fracbit = fxp & mask
|
||||||
|
n = 1
|
||||||
|
frac = ""
|
||||||
|
|
||||||
|
if fracbit == 0:
|
||||||
|
return whole
|
||||||
|
|
||||||
|
# The same method can be applied backwards.
|
||||||
|
# 0.1110101 = 0.abcdefgh ...
|
||||||
|
# where abcdefgh... are decimal digits. Then multiply by 10 to
|
||||||
|
# get
|
||||||
|
# 1001.0010010 = a.bcdefgh ...
|
||||||
|
# therefore a = 0b1001 = 9. Then use a bitmask to get
|
||||||
|
# 0.0010010 = 0.bcdefgh ...
|
||||||
|
# etc.
|
||||||
|
|
||||||
|
for i in range(0, fracnum):
|
||||||
|
fracbit = fracbit * 10
|
||||||
|
frac = frac + str(fracbit >> fracnum)
|
||||||
|
fracbit = fracbit & mask
|
||||||
|
return whole + "." + frac
|
|
@ -26,4 +26,4 @@ arty.dtb: arty.dts
|
||||||
dtc -O dtb -o arty.dtb arty.dts
|
dtc -O dtb -o arty.dtb arty.dts
|
||||||
|
|
||||||
mmio.py: csr2mp.py csr.json csr_bitwidth.json
|
mmio.py: csr2mp.py csr.json csr_bitwidth.json
|
||||||
python3 csr2mp.py > mmio.py
|
python3 csr2mp.py csr.json csr_bitwidth.json > mmio.py
|
||||||
|
|
|
@ -154,8 +154,9 @@ class MicropythonGenerator(InterfaceGenerator):
|
||||||
return f'{indent}{acc[0]} = {varname}\n'
|
return f'{indent}{acc[0]} = {varname}\n'
|
||||||
else:
|
else:
|
||||||
assert len(acc) == 2
|
assert len(acc) == 2
|
||||||
return f'{indent}{acc[0]} = {varname} & 0xFFFFFFFF\n' + \
|
# Little Endian. See linux kernel, include/linux/litex.h
|
||||||
f'{indent}{acc[1]} = {varname} >> 32\n'
|
return f'{indent}{acc[1]} = {varname} & 0xFFFFFFFF\n' + \
|
||||||
|
f'{indent}{acc[0]} = {varname} >> 32\n'
|
||||||
|
|
||||||
def print_read_register(self, indent, varname, reg, num):
|
def print_read_register(self, indent, varname, reg, num):
|
||||||
acc = self.get_accessor(reg, num)
|
acc = self.get_accessor(reg, num)
|
||||||
|
@ -231,8 +232,10 @@ if __name__ == "__main__":
|
||||||
MMIORegister("cl_in_loop", read_only=True),
|
MMIORegister("cl_in_loop", read_only=True),
|
||||||
MMIORegister("cl_cmd"),
|
MMIORegister("cl_cmd"),
|
||||||
MMIORegister("cl_word_in"),
|
MMIORegister("cl_word_in"),
|
||||||
|
MMIORegister("cl_word_out", read_only=True),
|
||||||
MMIORegister("cl_start_cmd"),
|
MMIORegister("cl_start_cmd"),
|
||||||
MMIORegister("cl_finish_cmd", read_only=True),
|
MMIORegister("cl_finish_cmd", read_only=True),
|
||||||
|
MMIORegister("cl_z_report", read_only=True),
|
||||||
]
|
]
|
||||||
csrh = CSRHandler(sys.argv[1], sys.argv[2], registers)
|
csrh = CSRHandler(sys.argv[1], sys.argv[2], registers)
|
||||||
for r in registers:
|
for r in registers:
|
||||||
|
|
|
@ -296,9 +296,9 @@ m4_define(CL_DATA_WID, CL_CONSTS_WID)
|
||||||
input [CL_DATA_WID-1:0] cl_word_in,
|
input [CL_DATA_WID-1:0] cl_word_in,
|
||||||
output reg [CL_DATA_WID-1:0] cl_word_out,
|
output reg [CL_DATA_WID-1:0] cl_word_out,
|
||||||
input cl_start_cmd,
|
input cl_start_cmd,
|
||||||
output cl_finish_cmd
|
output cl_finish_cmd,
|
||||||
|
|
||||||
,output reg test_clock
|
output [DAC_DATA_WID-1:0] cl_z_report
|
||||||
);
|
);
|
||||||
|
|
||||||
assign set_low = 0;
|
assign set_low = 0;
|
||||||
|
@ -315,8 +315,6 @@ m4_dac_switch(DAC_PORTS, 5);
|
||||||
m4_dac_switch(DAC_PORTS, 6);
|
m4_dac_switch(DAC_PORTS, 6);
|
||||||
m4_dac_switch(DAC_PORTS, 7);
|
m4_dac_switch(DAC_PORTS, 7);
|
||||||
|
|
||||||
initial test_clock <= 0;
|
|
||||||
|
|
||||||
`define MAKE_TEST_CLOCK
|
`define MAKE_TEST_CLOCK
|
||||||
`ifdef MAKE_TEST_CLOCK
|
`ifdef MAKE_TEST_CLOCK
|
||||||
reg [8-1:0] counter = 0;
|
reg [8-1:0] counter = 0;
|
||||||
|
@ -333,8 +331,6 @@ always @ (posedge clk) begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`else
|
|
||||||
assign test_clock = 0;
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
m4_adc_switch(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP);
|
m4_adc_switch(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP);
|
||||||
|
@ -385,7 +381,8 @@ control_loop #(
|
||||||
.word_in(cl_word_in),
|
.word_in(cl_word_in),
|
||||||
.word_out(cl_word_out),
|
.word_out(cl_word_out),
|
||||||
.start_cmd(cl_start_cmd),
|
.start_cmd(cl_start_cmd),
|
||||||
.finish_cmd(cl_finish_cmd)
|
.finish_cmd(cl_finish_cmd),
|
||||||
|
.z_report(cl_z_report)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -63,7 +63,9 @@ m4_define(M4_E_WID, (DAC_DATA_WID + 1))
|
||||||
input [M4_DATA_WID-1:0] word_in,
|
input [M4_DATA_WID-1:0] word_in,
|
||||||
output reg [M4_DATA_WID-1:0] word_out,
|
output reg [M4_DATA_WID-1:0] word_out,
|
||||||
input start_cmd,
|
input start_cmd,
|
||||||
output reg finish_cmd
|
output reg finish_cmd,
|
||||||
|
|
||||||
|
output [DAC_DATA_WID-1:0] z_report
|
||||||
);
|
);
|
||||||
|
|
||||||
/************ ADC and DAC modules ***************/
|
/************ ADC and DAC modules ***************/
|
||||||
|
@ -156,6 +158,7 @@ reg [DELAY_WID-1:0] dely_buffer = 0;
|
||||||
reg running = 0;
|
reg running = 0;
|
||||||
|
|
||||||
reg signed [DAC_DATA_WID-1:0] stored_dac_val = 0;
|
reg signed [DAC_DATA_WID-1:0] stored_dac_val = 0;
|
||||||
|
assign z_report = stored_dac_val;
|
||||||
reg [CYCLE_COUNT_WID-1:0] last_timer = 0;
|
reg [CYCLE_COUNT_WID-1:0] last_timer = 0;
|
||||||
reg [CYCLE_COUNT_WID-1:0] counting_timer = 0;
|
reg [CYCLE_COUNT_WID-1:0] counting_timer = 0;
|
||||||
reg [M4_CONSTS_WID-1:0] adjval_prev = 0;
|
reg [M4_CONSTS_WID-1:0] adjval_prev = 0;
|
||||||
|
|
|
@ -198,6 +198,7 @@ class Base(Module, AutoCSR):
|
||||||
self._make_csr("cl_word_out", CSRStatus, 64, "Control Loop Data Output")
|
self._make_csr("cl_word_out", CSRStatus, 64, "Control Loop Data Output")
|
||||||
self._make_csr("cl_start_cmd", CSRStorage, 1, "Control Loop Command Start Flag")
|
self._make_csr("cl_start_cmd", CSRStorage, 1, "Control Loop Command Start Flag")
|
||||||
self._make_csr("cl_finish_cmd", CSRStatus, 1, "Control Loop Command Finished Flag")
|
self._make_csr("cl_finish_cmd", CSRStatus, 1, "Control Loop Command Finished Flag")
|
||||||
|
self._make_csr("cl_z_report", CSRStatus, 1, "Control Loop Z Setting")
|
||||||
|
|
||||||
self.kwargs["i_clk"] = clk
|
self.kwargs["i_clk"] = clk
|
||||||
self.kwargs["i_rst_L"] = ~platform.request("module_reset")
|
self.kwargs["i_rst_L"] = ~platform.request("module_reset")
|
||||||
|
@ -208,7 +209,7 @@ class Base(Module, AutoCSR):
|
||||||
self.kwargs["o_adc_conv"] = platform.request("adc_conv")
|
self.kwargs["o_adc_conv"] = platform.request("adc_conv")
|
||||||
self.kwargs["i_adc_sdo"] = platform.request("adc_sdo")
|
self.kwargs["i_adc_sdo"] = platform.request("adc_sdo")
|
||||||
self.kwargs["o_adc_sck"] = platform.request("adc_sck")
|
self.kwargs["o_adc_sck"] = platform.request("adc_sck")
|
||||||
self.kwargs["o_test_clock"] = platform.request("test_clock")
|
# self.kwargs["o_test_clock"] = platform.request("test_clock")
|
||||||
self.kwargs["o_set_low"] = platform.request("differntial_output_low")
|
self.kwargs["o_set_low"] = platform.request("differntial_output_low")
|
||||||
|
|
||||||
""" Dump all MMIO pins to a JSON file with their exact bit widths. """
|
""" Dump all MMIO pins to a JSON file with their exact bit widths. """
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
from mmio import *
|
||||||
|
from comm import *
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
# The DAC always have to be init and reset
|
||||||
|
dac_init(0)
|
||||||
|
|
||||||
|
write_dac_sel(1 << 1, 0)
|
||||||
|
write_adc_sel(2 << 1, 0)
|
||||||
|
|
||||||
|
def cl_cmd_write(cmd, val):
|
||||||
|
write_cl_word_in(val)
|
||||||
|
write_cl_cmd(1 << 7 | cmd)
|
||||||
|
write_cl_start_cmd(1)
|
||||||
|
while not read_cl_finish_cmd():
|
||||||
|
print('aa')
|
||||||
|
write_cl_start_cmd(0)
|
||||||
|
|
||||||
|
def cl_cmd_read(cmd):
|
||||||
|
write_cl_cmd(cmd)
|
||||||
|
write_cl_start_cmd(1)
|
||||||
|
while not read_cl_finish_cmd():
|
||||||
|
print('aa')
|
||||||
|
write_cl_start_cmd(0)
|
||||||
|
return read_cl_word_out()
|
||||||
|
|
||||||
|
cl_cmd_write(2, int(argv[1])) # Setpoint
|
||||||
|
cl_cmd_write(3, int(argv[2])) # P
|
||||||
|
cl_cmd_write(4, int(argv[3])) # I
|
||||||
|
cl_cmd_write(8, int(argv[4])) # Delay
|
||||||
|
cl_cmd_write(1, 1)
|
|
@ -1,6 +1,8 @@
|
||||||
from comm import *
|
from comm import *
|
||||||
from time import sleep_ms
|
from time import sleep_ms
|
||||||
|
|
||||||
|
dac_init(0)
|
||||||
|
write_adc_sel(0,0)
|
||||||
for i in range(-300,300):
|
for i in range(-300,300):
|
||||||
dac_write_volt(i, 0)
|
dac_write_volt(i, 0)
|
||||||
for j in range(0,20):
|
for j in range(0,20):
|
||||||
|
|
Loading…
Reference in New Issue