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.
|
* 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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue