diff --git a/firmware/rtl/autoapproach/autoapproach_sim.cpp b/firmware/rtl/autoapproach/autoapproach_sim.cpp deleted file mode 100644 index 9412b30..0000000 --- a/firmware/rtl/autoapproach/autoapproach_sim.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include - -#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 { - 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; -} diff --git a/firmware/rtl/autoapproach/autoapproach_sim.v b/firmware/rtl/autoapproach/autoapproach_sim.v deleted file mode 100644 index 592f616..0000000 --- a/firmware/rtl/autoapproach/autoapproach_sim.v +++ /dev/null @@ -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 diff --git a/firmware/rtl/spi/spi_switch.v b/firmware/rtl/spi/spi_switch.v index 60c2e61..0616d94 100644 --- a/firmware/rtl/spi/spi_switch.v +++ b/firmware/rtl/spi/spi_switch.v @@ -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 diff --git a/firmware/rtl/autoapproach/Makefile b/firmware/rtl/waveform/Makefile similarity index 100% rename from firmware/rtl/autoapproach/Makefile rename to firmware/rtl/waveform/Makefile diff --git a/firmware/rtl/autoapproach/bram_dma.cpp b/firmware/rtl/waveform/bram_dma.cpp similarity index 100% rename from firmware/rtl/autoapproach/bram_dma.cpp rename to firmware/rtl/waveform/bram_dma.cpp diff --git a/firmware/rtl/autoapproach/bram_dma.hpp b/firmware/rtl/waveform/bram_dma.hpp similarity index 100% rename from firmware/rtl/autoapproach/bram_dma.hpp rename to firmware/rtl/waveform/bram_dma.hpp diff --git a/firmware/rtl/autoapproach/bram_interface.v b/firmware/rtl/waveform/bram_interface.v similarity index 100% rename from firmware/rtl/autoapproach/bram_interface.v rename to firmware/rtl/waveform/bram_interface.v diff --git a/firmware/rtl/autoapproach/bram_interface_sim.cpp b/firmware/rtl/waveform/bram_interface_sim.cpp similarity index 100% rename from firmware/rtl/autoapproach/bram_interface_sim.cpp rename to firmware/rtl/waveform/bram_interface_sim.cpp diff --git a/firmware/rtl/autoapproach/bram_interface_sim.v b/firmware/rtl/waveform/bram_interface_sim.v similarity index 100% rename from firmware/rtl/autoapproach/bram_interface_sim.v rename to firmware/rtl/waveform/bram_interface_sim.v diff --git a/firmware/rtl/autoapproach/dma_sim.v b/firmware/rtl/waveform/dma_sim.v similarity index 100% rename from firmware/rtl/autoapproach/dma_sim.v rename to firmware/rtl/waveform/dma_sim.v diff --git a/firmware/rtl/autoapproach/autoapproach.v b/firmware/rtl/waveform/waveform.v similarity index 67% rename from firmware/rtl/autoapproach/autoapproach.v rename to firmware/rtl/waveform/waveform.v index 1d9f244..473a095 100644 --- a/firmware/rtl/autoapproach/autoapproach.v +++ b/firmware/rtl/waveform/waveform.v @@ -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,23 +130,10 @@ 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; - end else begin state <= WAIT_ON_ARM; + end else begin + state <= DO_WAIT; 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; -end -endcase endmodule