move autoapproach to possibly useful waveform module: not yet tested
This commit is contained in:
parent
05f8878751
commit
89938a2ff6
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -4,7 +4,7 @@
|
|||
* This crossbar is entirely controlled by the kernel.
|
||||
*/
|
||||
module spi_crossbar #(
|
||||
parameter PORTS = 2,
|
||||
parameter PORTS = 8,
|
||||
(
|
||||
input select[PORTS-1:0],
|
||||
|
||||
|
@ -23,19 +23,27 @@ module spi_crossbar #(
|
|||
Do things the old, dumb way instead.
|
||||
*/
|
||||
|
||||
always @(*) begin
|
||||
if (select[1]) begin
|
||||
mosi = mosi_ports[1];
|
||||
miso = miso_ports[1];
|
||||
sck = sck_ports[1];
|
||||
ss = ss_ports[1];
|
||||
end else begin
|
||||
/* Select zeroth slot by default. No latches. */
|
||||
mosi = mosi_ports[0];
|
||||
miso = miso_ports[0];
|
||||
sck = sck_ports[0];
|
||||
ss = ss_ports[0];
|
||||
`define do_select(n) \
|
||||
mosi = mosi_ports[n]; \
|
||||
miso = miso_ports[n]; \
|
||||
sck = sck_ports[n]; \
|
||||
ss = ss_ports[n]
|
||||
|
||||
`define check_select(n) \
|
||||
if (select[n]) begin \
|
||||
do_select(n); \
|
||||
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
|
||||
|
||||
endmodule
|
||||
`undefineall
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/* Autoapproach module. This module applies a waveform located in memory
|
||||
* (and copied into Block RAM). This waveform is arbitrary but of fixed
|
||||
* length.
|
||||
* time in between sent sample, total period 10-50ms
|
||||
*/
|
||||
module autoapproach #(
|
||||
/* Write a waveform to a DAC. */
|
||||
module waveform #(
|
||||
parameter DAC_WID = 24,
|
||||
parameter DAC_DATA_WID = 20,
|
||||
parameter ADC_WID = 24,
|
||||
parameter DAC_WID_SIZ = 5,
|
||||
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 WORD_WID = 24,
|
||||
parameter WORD_AMNT_WID = 11,
|
||||
|
@ -17,11 +18,6 @@ module autoapproach #(
|
|||
) (
|
||||
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 */
|
||||
|
@ -36,15 +32,18 @@ module autoapproach #(
|
|||
input ram_valid,
|
||||
|
||||
/* 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 miso,
|
||||
output mosi,
|
||||
input sck,
|
||||
output ss_L
|
||||
);
|
||||
|
||||
wire [WORD_WID-1:0] word;
|
||||
reg word_next;
|
||||
wire word_ok;
|
||||
wire word_last;
|
||||
wire word_rst;
|
||||
|
||||
bram_interface #(
|
||||
.WORD_WID(WORD_WID),
|
||||
.WORD_AMNT_WID(WORD_AMNT_WID),
|
||||
|
@ -59,22 +58,46 @@ bram_interface #(
|
|||
.word_last(word_last),
|
||||
.word_ok(word_ok),
|
||||
.word_rst(word_rst),
|
||||
|
||||
.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)
|
||||
);
|
||||
|
||||
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 DO_WAIT = 1;
|
||||
localparam RECV_WORD = 2;
|
||||
localparam WAIT_ON_DAC = 3;
|
||||
localparam WAIT_ON_DETECTION = 4;
|
||||
localparam DETECTED = 5;
|
||||
reg [2:0] state = WAIT_ON_ARM;
|
||||
reg [1:0] state = WAIT_ON_ARM;
|
||||
|
||||
reg [TIMER_WID-1:0] wait_timer = 0;
|
||||
|
||||
|
@ -107,22 +130,9 @@ WAIT_ON_DAC: if (dac_finished) begin
|
|||
dac_arm <= 0;
|
||||
/* Was the last word read *the* last word? */
|
||||
if (word_last) begin
|
||||
state <= WAIT_ON_DETECTION;
|
||||
adc_arm <= 1;
|
||||
state <= WAIT_ON_ARM;
|
||||
end else begin
|
||||
state <= WAIT_ON_ARM;
|
||||
end
|
||||
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;
|
||||
state <= DO_WAIT;
|
||||
end
|
||||
endcase
|
||||
|
Loading…
Reference in New Issue