move autoapproach to possibly useful waveform module: not yet tested

This commit is contained in:
Peter McGoron 2023-03-03 18:30:00 +00:00
parent 05f8878751
commit 89938a2ff6
11 changed files with 69 additions and 272 deletions

View File

@ -1,125 +0,0 @@
#include <random>
#include <cmath>
#include "Vautoapproach_sim.h"
#include "../testbench.hpp"
/* TODO: generalize so bram_interface_sim can use it.
* This should make a triangle wave.
*/
class RefreshModule {
uint32_t *store_32;
size_t word_amnt;
bool pending_refresh_start;
public:
void posedge(uint8_t &refresh_start, uint32_t &start_addr,
uint8_t refresh_finished) {
if (refresh_start && refresh_finished) {
refresh_start = 0;
} else if (pending_refresh_start && !refresh_start) {
pending_refresh_start = false;
refresh_start = 1;
}
}
RefreshModule(size_t _word_amnt, size_t _start_addr)
: word_amnt{_word_amnt}
, start_addr{_start_addr} {
store_32 = new uint32_t[_start_addr];
for (size_t i = 0; i < start_addr; i++) {
/* 0xFFFFF is the maximum DAC value */
store_32[i] = 0xFFFFF*max(double)i/start_addr;
}
pending_refresh_start = true;
}
~RefreshModule() {
delete[] store_32;
}
};
/* TODO: make generic SPI delay class because this code has been duplicated
* many times over now. This function is also similar to the control loop
* ADC simulation. */
class GaussianZPiezo {
std::default_random_engine generator;
std::normal_distribution<> dist;
double scale;
double setpt;
double midpt;
double stretch;
double sample() {return scale*dist(generator);}
GaussianZPiezo(double scale, double mean, double dev, double setpt,
double midpt, double stretch, int seed,
uint16_t dac_wait_count,
uint16_t adc_wait_count)
: scale{scale}, dist{mean,dev}, generator{},
, setpt{setpt}, midpt{midpt}, stretch{stretch},
, dac_wait_count_max{dac_wait_count}
, adc_wait_count_max{adc_wait_count} {
if (seed < 0) {
std::random_device rd;
generator.seed(rd());
} else {
generator.seed(seed);
}
}
/* Sigmoid function. This function is
c(x-d)
f(x) = A*-------------------
sqrt(1+(c(x-d))^2)
where A is the setpoint and c is how compressed the sigmoid is.
*/
double f(uint32_t x) {
double x_shift = x - midpt + sample();
return setpt*stretch*x_shift/sqrt(fma(x_shift,x_shift,1));
}
public:
void posedge(uint8_t &dac_finished, uint8_t dac_arm,
uint32_t dac_out,
uint8_t &adc_finished, uint8_t adc_arm,
uint32_t &adc_out) {
if (adc_arm && adc_wait_counter == adc_wait_counter_max &&
!adc_finished) {
adc_finished = 1;
adc_out = sample();
} else if (!adc_arm) {
adc_finished = 0;
adc_wait_counter = 0;
} else {
adc_wait_counter++;
}
if (dac_arm && dac_wait_counter == dac_wait_counter_max &&
!dac_finished) {
dac_finished = 1;
}
};
class AA_TB : TB<Vautoapproach_sim> {
RefreshModule refresh;
GaussianZPiezo piezo;
void posedge() override;
AA_TB(size_t word_amnt, uint32_t start_addr)
: refresh{word_amnt, start_addr} {}
~AA_TB() {}
};
AA_TB::posedge() {
refresh.posedge(mod.refresh_start, mod.start_addr,
mod.refresh_finished);
}
int main(int argc, char **argv) {
return 0;
}

View File

@ -1,96 +0,0 @@
module autoapproach_sim #(
parameter DAC_WID = 24,
parameter DAC_DATA_WID = 20,
parameter ADC_WID = 24,
parameter TIMER_WID = 32,
parameter WORD_WID = 24,
parameter WORD_AMNT_WID = 11,
parameter [WORD_AMNT_WID-1:0] WORD_AMNT = 2047,
parameter RAM_WID = 32,
parameter RAM_WORD_WID = 16,
parameter RAM_WORD_INCR = 2,
parameter TOTAL_RAM_WORD_MINUS_ONE = 4095
) (
input clk,
input arm,
output stopped,
output detected,
input polarity,
input [ADC_WID-1:0] setpoint,
input [TIMER_WID-1:0] time_to_wait,
/* User interface */
input refresh_start,
input [RAM_WID-1:0] start_addr,
output refresh_finished,
/* DAC wires. */
input dac_finished,
output dac_arm,
output [DAC_WID-1:0] dac_out,
input adc_finished,
output adc_arm,
input [ADC_WID-1:0] measurement
input[RAM_WORD_WID-1:0] backing_store [TOTAL_RAM_WORD_MINUS_ONE:0]
);
wire [RAM_WID-1:0] ram_dma_addr;
wire [RAM_WORD_WID-1:0] ram_word;
wire ram_read;
wire ram_valid;
dma_sim #(
.RAM_WID(RAM_WID),
.RAM_WORD_WID(RAM_WORD_WID),
.RAM_REAL_START(RAM_REAL_START),
.RAM_CNTR_LEN(RAM_CNTR_LEN),
.TOTAL_RAM_WORD_MINUS_ONE(TOTAL_RAM_WORD_MINUS_ONE),
.DELAY_CNTR_LEN(DELAY_CNTR_LEN),
.DELAY_TOTAL(DELAY_TOTAL)
) dma_sim (
.clk(clk),
.ram_dma_addr(ram_dma_addr),
.ram_word(ram_word),
.ram_read(ram_read),
.ram_valid(ram_valid),
.backing_store(backing_store)
);
autoapproach #(
.DAC_WID(DAC_WID),
.DAC_DATA_WID(DAC_DATA_WID),
.ADC_WID(ADC_WID),
.TIMER_WID(TIMER_WID),
.WORD_WID(WORD_WID),
.WORD_AMNT_WID(WORD_AMNT_WID),
.WORD_AMNT(WORD_AMNT),
.RAM_WID(RAM_WID),
.RAM_WORD_WID(RAM_WORD_WID),
.RAM_WORD_INCR(RAM_WORD_INCR)
) aa (
.clk(clk),
.arm(arm),
.stopped(stopped),
.detected(detected),
.polarity(polarity),
.setpoint(setpoint),
.time_to_wait(time_to_wait),
.refresh_start(refresh_start),
.start_addr(start_addr),
.refresh_finished(refresh_finished),
.ram_dma_addr(ram_dma_addr),
.ram_word(ram_word),
.ram_read(ram_read),
.ram_valid(ram_valid),
.dac_finished(dac_finished),
.dac_arm(dac_arm),
.dac_out(dac_out),
.adc_finished(adc_finished),
.adc_arm(adc_arm),
.measurement(measurement)
);
endmodule

View File

@ -4,7 +4,7 @@
* This crossbar is entirely controlled by the kernel. * This crossbar is entirely controlled by the kernel.
*/ */
module spi_crossbar #( module spi_crossbar #(
parameter PORTS = 2, parameter PORTS = 8,
( (
input select[PORTS-1:0], input select[PORTS-1:0],
@ -23,19 +23,27 @@ module spi_crossbar #(
Do things the old, dumb way instead. Do things the old, dumb way instead.
*/ */
always @(*) begin `define do_select(n) \
if (select[1]) begin mosi = mosi_ports[n]; \
mosi = mosi_ports[1]; miso = miso_ports[n]; \
miso = miso_ports[1]; sck = sck_ports[n]; \
sck = sck_ports[1]; ss = ss_ports[n]
ss = ss_ports[1];
end else begin `define check_select(n) \
/* Select zeroth slot by default. No latches. */ if (select[n]) begin \
mosi = mosi_ports[0]; do_select(n); \
miso = miso_ports[0];
sck = sck_ports[0];
ss = ss_ports[0];
end end
always @(*) begin
check_select(7)
else check_select(6)
else check_select(5)
else check_select(4)
else check_select(3)
else check_select(2)
else check_select(1)
else do_select(0)
end end
endmodule endmodule
`undefineall

View File

@ -1,12 +1,13 @@
/* Autoapproach module. This module applies a waveform located in memory /* Write a waveform to a DAC. */
* (and copied into Block RAM). This waveform is arbitrary but of fixed module waveform #(
* length.
* time in between sent sample, total period 10-50ms
*/
module autoapproach #(
parameter DAC_WID = 24, parameter DAC_WID = 24,
parameter DAC_DATA_WID = 20, parameter DAC_WID_SIZ = 5,
parameter ADC_WID = 24, parameter DAC_POLARITY = 0,
parameter DAC_PHASE = 1,
parameter DAC_CYCLE_HALF_WAIT = 10,
parameter DAC_CYCLE_HALF_WAIT_SIZ = 4,
parameter DAC_SS_WAIT = 5,
parameter DAC_SS_WAIT_SIZ = 3,
parameter TIMER_WID = 32, parameter TIMER_WID = 32,
parameter WORD_WID = 24, parameter WORD_WID = 24,
parameter WORD_AMNT_WID = 11, parameter WORD_AMNT_WID = 11,
@ -17,11 +18,6 @@ module autoapproach #(
) ( ) (
input clk, input clk,
input arm, input arm,
output stopped,
output detected,
input polarity,
input [ADC_WID-1:0] setpoint,
input [TIMER_WID-1:0] time_to_wait, input [TIMER_WID-1:0] time_to_wait,
/* User interface */ /* User interface */
@ -36,15 +32,18 @@ module autoapproach #(
input ram_valid, input ram_valid,
/* DAC wires. */ /* DAC wires. */
input dac_finished, input miso,
output dac_arm, output mosi,
output [DAC_WID-1:0] dac_out, input sck,
output ss_L
input adc_finished,
output adc_arm,
input [ADC_WID-1:0] measurement
); );
wire [WORD_WID-1:0] word;
reg word_next;
wire word_ok;
wire word_last;
wire word_rst;
bram_interface #( bram_interface #(
.WORD_WID(WORD_WID), .WORD_WID(WORD_WID),
.WORD_AMNT_WID(WORD_AMNT_WID), .WORD_AMNT_WID(WORD_AMNT_WID),
@ -59,22 +58,46 @@ bram_interface #(
.word_last(word_last), .word_last(word_last),
.word_ok(word_ok), .word_ok(word_ok),
.word_rst(word_rst), .word_rst(word_rst),
.refresh_start(refresh_start), .refresh_start(refresh_start),
.start_addr(start_addr), .start_addr(start_addr),
.refresh_finished(refresh_finished), .refresh_finished(refresh_finished),
.ram_dma_addr(ram_dma_addr), .ram_dma_addr(ram_dma_addr),
.ram_word(ram_word), .ram_word(ram_word),
.ram_read(ram_read), .ram_read(ram_read),
.ram_valid(ram_valid) .ram_valid(ram_valid)
); );
wire dac_finished;
reg dac_arm;
reg [DAC_WID-1:0] dac_out;
spi_master_ss_no_read #(
.WID(DAC_WID),
.WID_LEN(DAC_WID_SIZ),
.CYCLE_HALF_WAIT(DAC_CYCLE_HALF_WAIT),
.TIMER_LEN(DAC_CYCLE_HALF_WAIT_SIZ),
.POLARITY(DAC_POLARITY),
.PHASE(DAC_PHASE),
.SS_WAIT(DAC_SS_WAIT),
.SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ)
) dac_master (
.clk(clk),
.mosi(mosi),
.miso(miso),
.sck_wire(sck),
.ss_L(ss_L),
.finished(dac_finished),
.arm(dac_arm),
.to_slave(dac_out)
);
localparam WAIT_ON_ARM = 0; localparam WAIT_ON_ARM = 0;
localparam DO_WAIT = 1; localparam DO_WAIT = 1;
localparam RECV_WORD = 2; localparam RECV_WORD = 2;
localparam WAIT_ON_DAC = 3; localparam WAIT_ON_DAC = 3;
localparam WAIT_ON_DETECTION = 4; reg [1:0] state = WAIT_ON_ARM;
localparam DETECTED = 5;
reg [2:0] state = WAIT_ON_ARM;
reg [TIMER_WID-1:0] wait_timer = 0; reg [TIMER_WID-1:0] wait_timer = 0;
@ -107,23 +130,10 @@ WAIT_ON_DAC: if (dac_finished) begin
dac_arm <= 0; dac_arm <= 0;
/* Was the last word read *the* last word? */ /* Was the last word read *the* last word? */
if (word_last) begin if (word_last) begin
state <= WAIT_ON_DETECTION;
adc_arm <= 1;
end else begin
state <= WAIT_ON_ARM; state <= WAIT_ON_ARM;
end else begin
state <= DO_WAIT;
end end
endcase endcase
WAIT_ON_DETECTION: if (adc_finished) begin
if ((polarity && measurement >= setpt) ||
(!polarity && measurement <= setpt)) begin
state <= DETECTED;
detected <= 1;
end
end
DETECTED: if (!arm) begin
state <= WAIT_ON_ARM;
detected <= 0;
end
endcase
endmodule endmodule