patch control loop math to newdac widths

This commit is contained in:
Peter McGoron 2023-06-27 16:01:04 -04:00
parent 291329b49e
commit 1a97dfa5aa
6 changed files with 17 additions and 78 deletions

View File

@ -39,8 +39,10 @@ def sign_extend(value, bits):
################### ###################
# Start a SSH connection to the server. # Start a SSH connection to the server.
print('connecting')
client = SSHClient('192.168.1.50', user='root', pkey='~/.ssh/upsilon_key') client = SSHClient('192.168.1.50', user='root', pkey='~/.ssh/upsilon_key')
# Upload the script. # Upload the script.
print('connected')
client.scp_send('../linux/noise_test.py', '/root/noise_test.py') client.scp_send('../linux/noise_test.py', '/root/noise_test.py')
# Run the script. # Run the script.
out = client.run_command('micropython noise_test.py') out = client.run_command('micropython noise_test.py')

View File

@ -7,12 +7,17 @@ beginner.
# Setup steps # Setup steps
Change directory to `build`. Do all of the following in the `build` folder.
## Installing OpenFPGALoader ## Installing OpenFPGALoader
Install [openFPGALoader][1]. If this program is not in your repositories, Install [openFPGALoader][1]. If this program is not in your repositories,
run `make openFPGALoader` to fetch and install the program. run `make openFPGALoader` to fetch and build the program. This will install
openFPGALoader locally.
Even if you install openFPGALoader locally, there are some files (udev rules)
that must be installed with administrative privleges. Check the documentation
for openFPGALoader.
[1]: https://trabucayre.github.io/openFPGALoader/index.html [1]: https://trabucayre.github.io/openFPGALoader/index.html

View File

@ -1,70 +0,0 @@
# Copyright (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.
# Functions for converting to and from fixed point in Python.
from math import log10, floor
from decimal import *
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

View File

@ -39,15 +39,15 @@ m4_define(M4_CONSTS_WID, (CONSTS_WHOLE + CONSTS_FRAC))
parameter [M4_CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000, parameter [M4_CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000,
/* To calculate this value: /* To calculate this value:
* Load doc/fixedpoint.py * Load doc/fixedpoint.py
* run bin(string_to_fixed_point(str((ADC_RANGE/2**ADC_WID)/(DAC_RANGE/2**DAC_WID)), CONSTS_FRAC)) * run bin(string_to_fixed_point(str((DAC_RANGE/2**DAC_WID)/(ADC_RANGE/2**ADC_WID)), CONSTS_FRAC))
* This value is the value to put below. * This value uses ADC_RANGE=20.48, DAC_RANGE=32
* This value uses ADC_RANGE=20.48, DAC_RANGE=30
* The ranges are the range of values REPRESENTABLE by the ADC and DAC, * The ranges are the range of values REPRESENTABLE by the ADC and DAC,
* not the values you expect to get! * not the values you expect to get!
*/ */
parameter [M4_CONSTS_WID-1:0] ADC_TO_DAC = parameter [M4_CONSTS_WID-1:0] ADC_TO_DAC =
/* 64'b0100000110001001001101110100101111000110101, */ /* 64'b0100000110001001001101110100101111000110101, */
64'b0101110111000000000000000000000000000000000, /* 64'b0101110111000000000000000000000000000000000, */
64'b0110010000000000000000000000000000000000000,
parameter CYCLE_COUNT_WID = 18, parameter CYCLE_COUNT_WID = 18,
parameter DAC_WID = 20 parameter DAC_WID = 20
m4_define(M4_E_WID, (DAC_WID + 1)) m4_define(M4_E_WID, (DAC_WID + 1))

View File

@ -37,7 +37,7 @@ static void init(int argc, char **argv) {
using V = int64_t; using V = int64_t;
constexpr V per100 = 0b010101011110011000; constexpr V per100 = 0b010101011110011000;
constexpr V adc_to_dac = 0b0101110111000000000000000000000000000000000; constexpr V adc_to_dac = 0b0110010000000000000000000000000000000000000;
static void calculate() { static void calculate() {
/* Multiplication adds an extra CONSTS_FRAC bits to the end, /* Multiplication adds an extra CONSTS_FRAC bits to the end,

View File

@ -27,7 +27,9 @@ module spi_switch #(
); );
/* Avoid using for loops, they might not synthesize correctly. /* Avoid using for loops, they might not synthesize correctly.
Do things the old, dumb way instead. * Do things the old, dumb way instead.
*
* TODO: Instead of bit vector, use regular numbers
*/ */
`define do_select(n) \ `define do_select(n) \