change constants, bring back automated control loop tests, validate
This commit is contained in:
parent
f4fbd5fd40
commit
d979344624
|
@ -11,6 +11,8 @@ csr.json build/digilent_arty/digilent_arty.bit: soc.py
|
||||||
clean:
|
clean:
|
||||||
rm -rf build csr.json overlay.config overlay.dts pin_io.h arty.dts arty.dtb
|
rm -rf build csr.json overlay.config overlay.dts pin_io.h arty.dts arty.dtb
|
||||||
cd rtl && make clean
|
cd rtl && make clean
|
||||||
|
test:
|
||||||
|
cd rtl && make test
|
||||||
|
|
||||||
arty.dts: csr.json
|
arty.dts: csr.json
|
||||||
litex_json2dts_linux csr.json > arty.dts
|
litex_json2dts_linux csr.json > arty.dts
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
all: make_base make_spi make_control_loop make_waveform
|
all: make_base make_spi make_control_loop
|
||||||
|
|
||||||
|
test:
|
||||||
|
cd control_loop && make test
|
||||||
make_base:
|
make_base:
|
||||||
cd base && make codegen
|
cd base && make codegen
|
||||||
make_spi:
|
make_spi:
|
||||||
|
|
|
@ -14,8 +14,8 @@ CONSTS_FRAC=43
|
||||||
E_WID=21
|
E_WID=21
|
||||||
|
|
||||||
test: obj_dir/Vcontrol_loop_sim_top obj_dir/Vcontrol_loop_math
|
test: obj_dir/Vcontrol_loop_sim_top obj_dir/Vcontrol_loop_math
|
||||||
# obj_dir/Vcontrol_loop_math
|
obj_dir/Vcontrol_loop_math
|
||||||
|
obj_dir/Vcontrol_loop_sim_top
|
||||||
obj_dir/Vcontrol_loop_math.mk: control_loop_math_sim.cpp ${COMMON} \
|
obj_dir/Vcontrol_loop_math.mk: control_loop_math_sim.cpp ${COMMON} \
|
||||||
${control_loop_math_verilog}
|
${control_loop_math_verilog}
|
||||||
verilator --cc --exe -Wall --trace --trace-fst \
|
verilator --cc --exe -Wall --trace --trace-fst \
|
||||||
|
|
|
@ -168,9 +168,7 @@ control_loop_math #(
|
||||||
.CONSTS_SIZ(CONSTS_SIZ),
|
.CONSTS_SIZ(CONSTS_SIZ),
|
||||||
.ADC_WID(ADC_WID),
|
.ADC_WID(ADC_WID),
|
||||||
.DAC_WID(DAC_DATA_WID),
|
.DAC_WID(DAC_DATA_WID),
|
||||||
.CYCLE_COUNT_WID(CYCLE_COUNT_WID),
|
.CYCLE_COUNT_WID(CYCLE_COUNT_WID)
|
||||||
.SEC_PER_CYCLE('b10101011110011000),
|
|
||||||
.ADC_TO_DAC({32'b01000001100, 32'b01001001101110100101111000110101})
|
|
||||||
) math (
|
) math (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_L(rst_L),
|
.rst_L(rst_L),
|
||||||
|
@ -252,7 +250,7 @@ end
|
||||||
* the main loop is clearing the dirty bit.
|
* the main loop is clearing the dirty bit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wire write_control = state == CYCLE_START || !running;
|
wire write_control = state == WAIT_ON_DAC || !running;
|
||||||
reg dirty_bit = 0;
|
reg dirty_bit = 0;
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
|
|
|
@ -32,10 +32,17 @@ m4_define(M4_CONSTS_WID, (CONSTS_WHOLE + CONSTS_FRAC))
|
||||||
|
|
||||||
parameter ADC_WID = 18,
|
parameter ADC_WID = 18,
|
||||||
parameter [M4_CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000,
|
parameter [M4_CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000,
|
||||||
/* The conversion between the ADC bit (20/2**18) and DAC bit (20.48/2**20)
|
/* To calculate this value:
|
||||||
* is 0.256.
|
* Load doc/fixedpoint.py
|
||||||
|
* run bin(string_to_fixed_point(str((ADC_RANGE/2**ADC_WID)/(DAC_RANGE/2**DAC_WID)), CONSTS_FRAC))
|
||||||
|
* This value is the value to put below.
|
||||||
|
* This value uses ADC_RANGE=20.48, DAC_RANGE=30
|
||||||
|
* The ranges are the range of values REPRESENTABLE by the ADC and DAC,
|
||||||
|
* not the values you expect to get!
|
||||||
*/
|
*/
|
||||||
parameter [M4_CONSTS_WID-1:0] ADC_TO_DAC = 64'b0100000110001001001101110100101111000110101,
|
parameter [M4_CONSTS_WID-1:0] ADC_TO_DAC =
|
||||||
|
/* 64'b0100000110001001001101110100101111000110101, */
|
||||||
|
64'b0101110111000000000000000000000000000000000,
|
||||||
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))
|
||||||
|
|
|
@ -25,13 +25,14 @@ static void init(int argc, char **argv) {
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
mod = new ModType;
|
mod = new ModType;
|
||||||
mod->clk = 0;
|
mod->clk = 0;
|
||||||
|
mod->rst_L = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MASK(n) ((1 << (n)) - 1)
|
#define MASK(n) ((1 << (n)) - 1)
|
||||||
using V = int64_t;
|
using V = int64_t;
|
||||||
|
|
||||||
constexpr V per100 = 0b010101011110011000;
|
constexpr V per100 = 0b010101011110011000;
|
||||||
constexpr V adc_to_dac = 0b0100000110001001001101110100101111000110101;
|
constexpr V adc_to_dac = 0b0101110111000000000000000000000000000000000;
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
@ -7,14 +7,12 @@
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
// Other classes implemented (Verilator)
|
|
||||||
#include <verilated.h>
|
#include <verilated.h>
|
||||||
#include "control_loop_math_implementation.h"
|
#include "control_loop_math_implementation.h"
|
||||||
#include "control_loop_cmds.h"
|
#include "control_loop_cmds.h"
|
||||||
#include "Vcontrol_loop_sim_top.h"
|
#include "Vcontrol_loop_sim_top.h"
|
||||||
using ModType = Vcontrol_loop_sim_top;
|
using ModType = Vcontrol_loop_sim_top;
|
||||||
|
|
||||||
// Clock
|
|
||||||
uint32_t main_time = 0;
|
uint32_t main_time = 0;
|
||||||
double sc_time_stamp() {
|
double sc_time_stamp() {
|
||||||
return main_time;
|
return main_time;
|
||||||
|
@ -35,6 +33,7 @@ static void init(int argc, char **argv) {
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
mod = new ModType;
|
mod = new ModType;
|
||||||
mod->clk = 0;
|
mod->clk = 0;
|
||||||
|
mod->rst_L = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_value(V val, unsigned name) {
|
static void set_value(V val, unsigned name) {
|
||||||
|
@ -48,125 +47,42 @@ static void set_value(V val, unsigned name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
printf("sim top\n");
|
||||||
init(argc, argv);
|
init(argc, argv);
|
||||||
|
Transfer func = Transfer{150, 0, 2, 1.1, 10, -1};
|
||||||
|
|
||||||
int Con, // Continue option for user
|
set_value(0b11010111000010100011110101110000101000111, CONTROL_LOOP_P);
|
||||||
P = 3, // Default P value
|
/* Constant values must be sized to 64 bits, or else the compiler
|
||||||
I = 0, // Default I value
|
* will think they are 32 bit and silently mess things up
|
||||||
Delay = 20, // Default Delay value
|
*/
|
||||||
SetPt = 10000, // Default SetPt value
|
set_value((V)6 << CONSTS_FRAC, CONTROL_LOOP_I);
|
||||||
Status = 1, // Default Status value
|
set_value(20, CONTROL_LOOP_DELAY);
|
||||||
Option_Picked; // Option user picked
|
set_value(10000, CONTROL_LOOP_SETPT);
|
||||||
|
set_value(1, CONTROL_LOOP_STATUS);
|
||||||
|
mod->curset = 0;
|
||||||
|
|
||||||
do
|
for (int tick = 0; tick < 1000;) {
|
||||||
{
|
run_clock();
|
||||||
|
if (mod->request && !mod->fulfilled) {
|
||||||
mod = new ModType;
|
/* Verilator values are not sign-extended to the
|
||||||
Transfer func = Transfer{150, 0, 2, 1.1, 10, -1};
|
* size of type, so we have to do that ourselves.
|
||||||
|
*/
|
||||||
mod->clk = 0;
|
V ext = sign_extend(mod->curset, 20);
|
||||||
|
V val = func.val(ext);
|
||||||
// Testing this char for P value
|
printf("setting: %ld, val: %ld\n", ext, val);
|
||||||
char Data_Change_S = '0b11010111000010100011110101110000101000111';
|
mod->measured_value = val;
|
||||||
|
mod->fulfilled = 1;
|
||||||
// Default value for P, some type of error where it won't accept any string, int | Try char next time
|
} else if (mod->fulfilled && !mod->request) {
|
||||||
set_value(0b11010111000010100011110101110000101000111, CONTROL_LOOP_P);
|
mod->fulfilled = 0;
|
||||||
|
tick++;
|
||||||
// Default value
|
|
||||||
set_value((V)6 << CONSTS_FRAC, CONTROL_LOOP_I);
|
|
||||||
set_value(Delay, CONTROL_LOOP_DELAY);
|
|
||||||
set_value(SetPt, CONTROL_LOOP_SETPT);
|
|
||||||
set_value(Status, CONTROL_LOOP_STATUS);
|
|
||||||
|
|
||||||
// Menu
|
|
||||||
do
|
|
||||||
{
|
|
||||||
printf("%15s\n", "Menu");
|
|
||||||
printf("1) Set Control loop P Current value: %d\n", P);
|
|
||||||
printf("2) Set Control loop I Current value: %d\n", I);
|
|
||||||
printf("3) Set Delay Current value: %d\n", Delay);
|
|
||||||
printf("4) Set setpoint Current value: %d\n", SetPt);
|
|
||||||
printf("5) Set status Current value: %d\n", Status);
|
|
||||||
printf("6) Continue\n");
|
|
||||||
|
|
||||||
// Checks for what option user picks
|
|
||||||
scanf("%d", &Option_Picked);
|
|
||||||
|
|
||||||
// Clears unix screen
|
|
||||||
system("clear");
|
|
||||||
|
|
||||||
switch (Option_Picked)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
// This case doesn't work for some reason? Need further time to figure it out
|
|
||||||
printf("Please input new Control Loop P value: ");
|
|
||||||
scanf("%d", &P);
|
|
||||||
set_value(P, CONTROL_LOOP_P);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printf("Please input new Control Loop I value: ");
|
|
||||||
scanf("%d", &I);
|
|
||||||
set_value(I, CONTROL_LOOP_I);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
printf("Please input new delay value: ");
|
|
||||||
scanf("%d", &Delay);
|
|
||||||
set_value(Delay, CONTROL_LOOP_DELAY);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
printf("Please input new setpoint value: ");
|
|
||||||
scanf("%d", &SetPt);
|
|
||||||
set_value(SetPt, CONTROL_LOOP_SETPT);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
printf("Please input new status value: ");
|
|
||||||
scanf("%d", &Status);
|
|
||||||
set_value(Status, CONTROL_LOOP_STATUS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (Option_Picked != 6);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mod->curset = 0;
|
|
||||||
|
|
||||||
// Resets Con to 1 to activate for loop
|
|
||||||
Con = 1;
|
|
||||||
|
|
||||||
for (int tick = 0; Con == 1; tick++) {
|
|
||||||
run_clock();
|
|
||||||
if (mod->request && !mod->fulfilled) {
|
|
||||||
/* Verilator values are not sign-extended to the
|
|
||||||
* size of type, so we have to do that ourselves.
|
|
||||||
*/
|
|
||||||
V ext = sign_extend(mod->curset, 20);
|
|
||||||
V val = func.val(ext);
|
|
||||||
printf("setting: %ld, val: %ld\n", ext, val);
|
|
||||||
mod->measured_value = val;
|
|
||||||
mod->fulfilled = 1;
|
|
||||||
} else if (mod->fulfilled && !mod->request) {
|
|
||||||
mod->fulfilled = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mod->finish_cmd) {
|
|
||||||
mod->start_cmd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// After 100000 ticks shows user prompt, might make tick to be changable for user.
|
|
||||||
if (tick % 100000 == 0 && tick != 0)
|
|
||||||
{
|
|
||||||
printf("Continue? (0 for exit, 1 for yes, 2 to return to menu)\n");
|
|
||||||
scanf("%d", &Con);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Clears unix screen
|
|
||||||
system("clear");
|
|
||||||
|
|
||||||
mod->final();
|
if (mod->finish_cmd) {
|
||||||
delete mod;
|
mod->start_cmd = 0;
|
||||||
} while (Con == 2);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod->final();
|
||||||
|
delete mod;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include <memory>
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Other classes implemented (Verilator)
|
||||||
|
#include <verilated.h>
|
||||||
|
#include "control_loop_math_implementation.h"
|
||||||
|
#include "control_loop_cmds.h"
|
||||||
|
#include "Vcontrol_loop_sim_top.h"
|
||||||
|
using ModType = Vcontrol_loop_sim_top;
|
||||||
|
|
||||||
|
// Clock
|
||||||
|
uint32_t main_time = 0;
|
||||||
|
double sc_time_stamp() {
|
||||||
|
return main_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModType *mod;
|
||||||
|
|
||||||
|
static void run_clock() {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
mod->clk = !mod->clk;
|
||||||
|
mod->eval();
|
||||||
|
main_time++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init(int argc, char **argv) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
mod = new ModType;
|
||||||
|
mod->clk = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(V val, unsigned name) {
|
||||||
|
mod->cmd = CONTROL_LOOP_WRITE_BIT | name;
|
||||||
|
mod->word_into_loop = val;
|
||||||
|
mod->start_cmd = 1;
|
||||||
|
|
||||||
|
do { run_clock(); } while (!mod->finish_cmd);
|
||||||
|
mod->start_cmd = 0;
|
||||||
|
run_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
init(argc, argv);
|
||||||
|
|
||||||
|
int Con, // Continue option for user
|
||||||
|
P = 3, // Default P value
|
||||||
|
I = 0, // Default I value
|
||||||
|
Delay = 20, // Default Delay value
|
||||||
|
SetPt = 10000, // Default SetPt value
|
||||||
|
Status = 1, // Default Status value
|
||||||
|
Option_Picked; // Option user picked
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
|
||||||
|
mod = new ModType;
|
||||||
|
Transfer func = Transfer{150, 0, 2, 1.1, 10, -1};
|
||||||
|
|
||||||
|
mod->clk = 0;
|
||||||
|
|
||||||
|
// Testing this char for P value
|
||||||
|
char Data_Change_S = '0b11010111000010100011110101110000101000111';
|
||||||
|
|
||||||
|
// Default value for P, some type of error where it won't accept any string, int | Try char next time
|
||||||
|
set_value(0b11010111000010100011110101110000101000111, CONTROL_LOOP_P);
|
||||||
|
|
||||||
|
// Default value
|
||||||
|
set_value((V)6 << CONSTS_FRAC, CONTROL_LOOP_I);
|
||||||
|
set_value(Delay, CONTROL_LOOP_DELAY);
|
||||||
|
set_value(SetPt, CONTROL_LOOP_SETPT);
|
||||||
|
set_value(Status, CONTROL_LOOP_STATUS);
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("%15s\n", "Menu");
|
||||||
|
printf("1) Set Control loop P Current value: %d\n", P);
|
||||||
|
printf("2) Set Control loop I Current value: %d\n", I);
|
||||||
|
printf("3) Set Delay Current value: %d\n", Delay);
|
||||||
|
printf("4) Set setpoint Current value: %d\n", SetPt);
|
||||||
|
printf("5) Set status Current value: %d\n", Status);
|
||||||
|
printf("6) Continue\n");
|
||||||
|
|
||||||
|
// Checks for what option user picks
|
||||||
|
scanf("%d", &Option_Picked);
|
||||||
|
|
||||||
|
// Clears unix screen
|
||||||
|
system("clear");
|
||||||
|
|
||||||
|
switch (Option_Picked)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
// This case doesn't work for some reason? Need further time to figure it out
|
||||||
|
printf("Please input new Control Loop P value: ");
|
||||||
|
scanf("%d", &P);
|
||||||
|
set_value(P, CONTROL_LOOP_P);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("Please input new Control Loop I value: ");
|
||||||
|
scanf("%d", &I);
|
||||||
|
set_value(I, CONTROL_LOOP_I);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf("Please input new delay value: ");
|
||||||
|
scanf("%d", &Delay);
|
||||||
|
set_value(Delay, CONTROL_LOOP_DELAY);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
printf("Please input new setpoint value: ");
|
||||||
|
scanf("%d", &SetPt);
|
||||||
|
set_value(SetPt, CONTROL_LOOP_SETPT);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
printf("Please input new status value: ");
|
||||||
|
scanf("%d", &Status);
|
||||||
|
set_value(Status, CONTROL_LOOP_STATUS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (Option_Picked != 6);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mod->curset = 0;
|
||||||
|
|
||||||
|
// Resets Con to 1 to activate for loop
|
||||||
|
Con = 1;
|
||||||
|
|
||||||
|
for (int tick = 0; Con == 1; tick++) {
|
||||||
|
run_clock();
|
||||||
|
if (mod->request && !mod->fulfilled) {
|
||||||
|
/* Verilator values are not sign-extended to the
|
||||||
|
* size of type, so we have to do that ourselves.
|
||||||
|
*/
|
||||||
|
V ext = sign_extend(mod->curset, 20);
|
||||||
|
V val = func.val(ext);
|
||||||
|
printf("setting: %ld, val: %ld\n", ext, val);
|
||||||
|
mod->measured_value = val;
|
||||||
|
mod->fulfilled = 1;
|
||||||
|
} else if (mod->fulfilled && !mod->request) {
|
||||||
|
mod->fulfilled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod->finish_cmd) {
|
||||||
|
mod->start_cmd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After 100000 ticks shows user prompt, might make tick to be changable for user.
|
||||||
|
if (tick % 100000 == 0 && tick != 0)
|
||||||
|
{
|
||||||
|
printf("Continue? (0 for exit, 1 for yes, 2 to return to menu)\n");
|
||||||
|
scanf("%d", &Con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Clears unix screen
|
||||||
|
system("clear");
|
||||||
|
|
||||||
|
mod->final();
|
||||||
|
delete mod;
|
||||||
|
} while (Con == 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue