raster simulate
This commit is contained in:
parent
013774e28b
commit
96e9a3d043
|
@ -3,7 +3,7 @@
|
|||
.PHONY: test clean
|
||||
|
||||
|
||||
test: obj_dir/Vram_fifo obj_dir/Vram_shim
|
||||
test: obj_dir/Vram_fifo obj_dir/Vram_shim obj_dir/Vraster_sim
|
||||
|
||||
RAM_FIFO_SRC= ram_fifo.v ram_fifo_dual_port.v ram_fifo_sim.cpp
|
||||
obj_dir/Vram_fifo.mk: ${RAM_FIFO_SRC}
|
||||
|
@ -11,7 +11,7 @@ obj_dir/Vram_fifo.mk: ${RAM_FIFO_SRC}
|
|||
${RAM_FIFO_SRC}
|
||||
obj_dir/Vram_fifo: obj_dir/Vram_fifo.mk
|
||||
cd obj_dir && make -f Vram_fifo.mk
|
||||
@./obj_dir/Vram_fifo && echo 'Vram_fifo successful'
|
||||
@./obj_dir/Vram_fifo && echo 'ram_fifo successful'
|
||||
|
||||
RAM_SHIM_SRC= ram_shim.v ram_fifo.v ram_fifo_dual_port.v ram_shim_sim.cpp
|
||||
obj_dir/Vram_shim.mk: ${RAM_SHIM_SRC} ram_shim_cmds.vh ram_shim_cmds.h
|
||||
|
@ -20,14 +20,26 @@ obj_dir/Vram_shim.mk: ${RAM_SHIM_SRC} ram_shim_cmds.vh ram_shim_cmds.h
|
|||
${RAM_SHIM_SRC}
|
||||
obj_dir/Vram_shim: obj_dir/Vram_shim.mk ram_shim_sim.cpp
|
||||
cd obj_dir && make -f Vram_shim.mk
|
||||
@./obj_dir/Vram_shim && echo 'Vram_shim successful'
|
||||
@./obj_dir/Vram_shim && echo 'ram_shim successful'
|
||||
|
||||
RASTER_SIM_SRC = raster_sim.v raster.v ram_shim.v ram_fifo.v ram_fifo_dual_port.v raster_sim.cpp
|
||||
|
||||
obj_dir/Vraster_sim.mk: ${RASTER_SIM_SRC} raster_cmds.vh raster_cmds.h ram_shim_cmds.vh ram_shim_cmds.h
|
||||
verilator --cc --exe -Wall --trace --trace-fst -CFLAGS -Wall \
|
||||
${RASTER_SIM_SRC}
|
||||
obj_dir/Vraster_sim: obj_dir/Vraster_sim.mk raster_sim.cpp
|
||||
cd obj_dir && make -f Vraster_sim.mk
|
||||
@./obj_dir/Vraster_sim && echo 'raster successful'
|
||||
|
||||
####### Codegen ########
|
||||
|
||||
ram_shim_cmds.h: ram_shim_cmds.vh
|
||||
echo '#pragma once' > ram_shim_cmds.h
|
||||
sed 's/`define/#define/g; s/`//g' ram_shim_cmds.vh >> ram_shim_cmds.h
|
||||
raster_cmds.h: raster_cmds.vh
|
||||
echo '#pragma once' > raster_cmds.h
|
||||
sed 's/`define/#define/g; s/`//g' raster_cmds.vh >> raster_cmds.h
|
||||
|
||||
clean:
|
||||
rm -rf obj_dir
|
||||
rm *.vcd ram_shim_cmds.h
|
||||
rm -f *.vcd ram_shim_cmds.h
|
||||
|
|
|
@ -8,50 +8,50 @@
|
|||
`include "raster_cmds.vh"
|
||||
`timescale 10ns/10ns
|
||||
module raster #(
|
||||
parameter SAMPLEWID = 9,
|
||||
parameter DAC_DATA_WID = 20,
|
||||
parameter DAC_WID = 24,
|
||||
parameter DAC_WAIT_BETWEEN_CMD = 10,
|
||||
parameter TIMER_WID = 4,
|
||||
parameter STEPWID = 16,
|
||||
parameter ADCNUM = 9,
|
||||
parameter MAX_ADC_DATA_WID = 24
|
||||
parameter DAC_WAIT_BETWEEN_CMD = 10
|
||||
) (
|
||||
input clk,
|
||||
`ifdef VERILATOR
|
||||
output is_running,
|
||||
`endif
|
||||
|
||||
/* Kernel interface. */
|
||||
input [`RASTER_CMD_WID-1:0] kernel_cmd,
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input [`RASTER_DATA_WID-1:0] kernel_data_in,
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
output reg [`RASTER_DATA_WID-1:0] kernel_data_out,
|
||||
input kernel_ready,
|
||||
output reg kernel_finished,
|
||||
|
||||
/* X and Y DAC piezos */
|
||||
output x_arm,
|
||||
output [DAC_WID-1:0] x_to_dac,
|
||||
output [`DAC_WID-1:0] x_to_dac,
|
||||
/* verilator lint_off UNUSED */
|
||||
input [DAC_WID-1:0] x_from_dac,
|
||||
input [`DAC_WID-1:0] x_from_dac,
|
||||
/* verilator lint_on UNUSED */
|
||||
input x_finished,
|
||||
|
||||
output y_arm,
|
||||
output [DAC_WID-1:0] y_to_dac,
|
||||
output [`DAC_WID-1:0] y_to_dac,
|
||||
/* verilator lint_off UNUSED */
|
||||
input [DAC_WID-1:0] y_from_dac,
|
||||
input [`DAC_WID-1:0] y_from_dac,
|
||||
/* verilator lint_on UNUSED */
|
||||
input y_finished,
|
||||
|
||||
/* Connections to all possible ADCs. These are connected to SPI masters
|
||||
* and they will automatically extend ADC value lengths to their highest
|
||||
* values. */
|
||||
output reg [ADCNUM-1:0] adc_arm,
|
||||
output reg [`ADCNUM-1:0] adc_arm,
|
||||
|
||||
/* Yosys does not support input arrays. */
|
||||
input [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data,
|
||||
input [ADCNUM-1:0] adc_finished,
|
||||
input [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data,
|
||||
input [`ADCNUM-1:0] adc_finished,
|
||||
|
||||
/* RAM DMA. This is generally not directly connected to the
|
||||
* DMA IP. A shim is used in order to write multiple words
|
||||
* to memory. */
|
||||
output reg [MAX_ADC_DATA_WID-1:0] data,
|
||||
output reg [`MAX_ADC_DATA_WID-1:0] data,
|
||||
output reg mem_commit,
|
||||
input mem_finished
|
||||
);
|
||||
|
@ -101,43 +101,45 @@ module raster #(
|
|||
*/
|
||||
|
||||
localparam WAIT_ON_ARM = 0;
|
||||
localparam GET_DAC_VALUES = 1;
|
||||
localparam REQUEST_DAC_VALUES = 2;
|
||||
localparam MEASURE = 3;
|
||||
localparam SCAN_ADC_VALUES = 4;
|
||||
localparam ADVANCE_DAC_WRITE = 5;
|
||||
localparam WAIT_ADVANCE = 6;
|
||||
localparam REQUEST_DAC_VALUES = 1;
|
||||
localparam GET_DAC_VALUES = 2;
|
||||
localparam WAIT_ADVANCE = 3;
|
||||
localparam MEASURE = 4;
|
||||
localparam SCAN_ADC_VALUES = 5;
|
||||
localparam ADVANCE_DAC_WRITE = 6;
|
||||
localparam NEXT_LINE = 7;
|
||||
localparam WAIT_ON_ARM_DEASSERT = 8;
|
||||
localparam STATE_WID = 4;
|
||||
|
||||
/********** Loop State ***********/
|
||||
reg [STATE_WID-1:0] state = WAIT_ON_ARM;
|
||||
reg [SAMPLEWID-1:0] sample = 0;
|
||||
reg [SAMPLEWID-1:0] line = 0;
|
||||
reg [TIMER_WID-1:0] counter = 0;
|
||||
reg signed [DAC_DATA_WID-1:0] x_val = 0;
|
||||
reg signed [DAC_DATA_WID-1:0] y_val = 0;
|
||||
reg [`SAMPLEWID-1:0] sample = 0;
|
||||
reg [`SAMPLEWID-1:0] line = 0;
|
||||
reg [`TIMERWID-1:0] counter = 0;
|
||||
reg signed [`DAC_DATA_WID-1:0] x_val = 0;
|
||||
reg signed [`DAC_DATA_WID-1:0] y_val = 0;
|
||||
|
||||
/* Buffer to store all measured ADC values. This
|
||||
* is shifted until it is all zeros to determine
|
||||
* which ADC values should be read off.
|
||||
*/
|
||||
reg [ADCNUM-1:0] adc_used_tmp = 0;
|
||||
reg [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data_tmp = 0;
|
||||
reg [`ADCNUM-1:0] adc_used_tmp = 0;
|
||||
reg [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data_tmp = 0;
|
||||
|
||||
/********** Loop Parameters *************/
|
||||
reg [ADCNUM-1:0] adc_used = 0;
|
||||
reg [`ADCNUM-1:0] adc_used = 0;
|
||||
reg is_reverse = 0;
|
||||
reg arm = 0;
|
||||
reg running = 0;
|
||||
reg signed [DAC_DATA_WID-1:0] dx = 0;
|
||||
reg signed [DAC_DATA_WID-1:0] dy = 0;
|
||||
reg [TIMER_WID-1:0] settle_time = 0;
|
||||
`ifdef VERILATOR
|
||||
assign is_running = running;
|
||||
`endif
|
||||
reg signed [`DAC_DATA_WID-1:0] dx = 0;
|
||||
reg signed [`DAC_DATA_WID-1:0] dy = 0;
|
||||
reg [`TIMERWID-1:0] settle_time = 0;
|
||||
|
||||
reg [SAMPLEWID-1:0] max_samples = 0;
|
||||
reg [SAMPLEWID-1:0] max_lines = 0;
|
||||
reg [STEPWID-1:0] steps_per_sample = 0;
|
||||
reg [`SAMPLEWID-1:0] max_samples = 0;
|
||||
reg [`SAMPLEWID-1:0] max_lines = 0;
|
||||
|
||||
/********** Control Interface ************
|
||||
* This code assumes that RASTER_DATA_WID is greater than all registers.
|
||||
|
@ -161,25 +163,26 @@ end
|
|||
// Generates code to handle write requests from the kernel.
|
||||
`define generate_register(code, width, register) \
|
||||
`generate_register_read(code, width, register) \
|
||||
code | `RASTER_WRITE_BIT: begin \
|
||||
if (!running && (code) != `RASTER_ARM) begin \
|
||||
code | `RASTER_WRITE_BIT: \
|
||||
if (!running || (code) == `RASTER_ARM) begin \
|
||||
register <= kernel_data_in[(width)-1:0]; \
|
||||
kernel_finished <= 1; \
|
||||
end \
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (!kernel_ready) kernel_finished <= 0;
|
||||
else if (kernel_ready) begin case (kernel_cmd)
|
||||
`generate_register(`RASTER_MAX_SAMPLES, SAMPLEWID, max_samples)
|
||||
`generate_register(`RASTER_MAX_LINES, SAMPLEWID, max_lines)
|
||||
`generate_register(`RASTER_SETTLE_TIME, TIMER_WID, settle_time)
|
||||
`generate_register(`RASTER_DX, DAC_DATA_WID, dx)
|
||||
`generate_register(`RASTER_DY, DAC_DATA_WID, dy)
|
||||
`generate_register(`RASTER_USED_ADCS, ADCNUM, adc_used)
|
||||
`generate_register(`RASTER_STEPS_PER_SAMPLE, STEPWID, steps_per_sample)
|
||||
`generate_register(`RASTER_MAX_SAMPLES, `SAMPLEWID, max_samples)
|
||||
`generate_register(`RASTER_MAX_LINES, `SAMPLEWID, max_lines)
|
||||
`generate_register(`RASTER_SETTLE_TIME, `TIMERWID, settle_time)
|
||||
`generate_register(`RASTER_DX, `DAC_DATA_WID, dx)
|
||||
`generate_register(`RASTER_DY, `DAC_DATA_WID, dy)
|
||||
`generate_register(`RASTER_USED_ADCS, `ADCNUM, adc_used)
|
||||
`generate_register(`RASTER_ARM, 1, arm)
|
||||
`generate_register_read(`RASTER_RUNNING, 1, running)
|
||||
`ifdef VERILATOR
|
||||
default: $error("unknown kernel message");
|
||||
`endif
|
||||
endcase end
|
||||
end
|
||||
`undef generate_register_read
|
||||
|
@ -234,8 +237,8 @@ always @ (posedge clk) begin
|
|||
x_arm <= 1;
|
||||
y_arm <= 1;
|
||||
end else if (x_finished && y_finished) begin
|
||||
x_val <= x_from_dac[DAC_DATA_WID-1:0];
|
||||
y_val <= y_from_dac[DAC_DATA_WID-1:0];
|
||||
x_val <= x_from_dac[`DAC_DATA_WID-1:0];
|
||||
y_val <= y_from_dac[`DAC_DATA_WID-1:0];
|
||||
|
||||
x_arm <= 0;
|
||||
y_arm <= 0;
|
||||
|
@ -262,7 +265,7 @@ always @ (posedge clk) begin
|
|||
end
|
||||
SCAN_ADC_VALUES: if (adc_used_tmp == 0 && !mem_commit) begin
|
||||
`CHECK_DAC_ARM
|
||||
if (sample == max_samples) begin
|
||||
if (sample == max_samples-1) begin
|
||||
dx <= ~dx + 1;
|
||||
dy <= ~dy + 1;
|
||||
|
||||
|
@ -275,6 +278,7 @@ always @ (posedge clk) begin
|
|||
is_reverse <= !is_reverse;
|
||||
sample <= 0;
|
||||
end else begin
|
||||
sample <= sample + 1;
|
||||
state <= ADVANCE_DAC_WRITE;
|
||||
end
|
||||
end else if (mem_finished) begin
|
||||
|
@ -284,9 +288,9 @@ always @ (posedge clk) begin
|
|||
end else begin
|
||||
`CHECK_DAC_ARM
|
||||
adc_used_tmp <= adc_used_tmp << 1;
|
||||
adc_data_tmp <= adc_data_tmp << MAX_ADC_DATA_WID;
|
||||
if (adc_used_tmp[ADCNUM-1]) begin
|
||||
data <= adc_data_tmp[ADCNUM*MAX_ADC_DATA_WID-1:(ADCNUM-1)*MAX_ADC_DATA_WID];
|
||||
adc_data_tmp <= adc_data_tmp << `MAX_ADC_DATA_WID;
|
||||
if (adc_used_tmp[`ADCNUM-1]) begin
|
||||
data <= adc_data_tmp[`ADCNUM*`MAX_ADC_DATA_WID-1:(`ADCNUM-1)*`MAX_ADC_DATA_WID];
|
||||
mem_commit <= 1;
|
||||
end
|
||||
end
|
||||
|
@ -298,7 +302,6 @@ always @ (posedge clk) begin
|
|||
y_to_dac <= {4'b0001, y_val + dy};
|
||||
x_arm <= 1;
|
||||
y_arm <= 1;
|
||||
sample <= sample + 1;
|
||||
end else if (x_finished && y_finished) begin
|
||||
counter <= 0;
|
||||
state <= WAIT_ADVANCE;
|
||||
|
@ -306,10 +309,10 @@ always @ (posedge clk) begin
|
|||
y_arm <= 0;
|
||||
end
|
||||
NEXT_LINE: if (!x_arm || !y_arm) begin
|
||||
if (line == max_lines) begin
|
||||
if (line == max_lines-1) begin
|
||||
state <= WAIT_ON_ARM_DEASSERT;
|
||||
running <= 0;
|
||||
end else begin
|
||||
sample <= 0;
|
||||
/* rotation of (dx,dy) by 90° -> (dy, -dx) */
|
||||
x_val <= x_val + dy;
|
||||
x_to_dac <= {4'b0001, x_val + dy};
|
||||
|
@ -327,6 +330,8 @@ always @ (posedge clk) begin
|
|||
end
|
||||
WAIT_ON_ARM_DEASSERT: if (!arm) begin
|
||||
state <= WAIT_ON_ARM;
|
||||
end else begin
|
||||
running <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
/* Make sure there are no gaps! The code generator will not work
|
||||
* correctly.
|
||||
*/
|
||||
`define RASTER_NOOP 0
|
||||
`define RASTER_MAX_SAMPLES 1
|
||||
`define RASTER_MAX_LINES 2
|
||||
|
@ -9,11 +6,20 @@
|
|||
`define RASTER_DY 5
|
||||
`define RASTER_ARM 6
|
||||
`define RASTER_USED_ADCS 7
|
||||
`define RASTER_STEPS_PER_SAMPLE 8
|
||||
`define RASTER_RUNNING 9
|
||||
`define RASTER_RUNNING 8
|
||||
|
||||
`define RASTER_WRITE_BIT (1 << (`RASTER_CMD_WID - 1))
|
||||
|
||||
`define RASTER_CMD_WID 8
|
||||
|
||||
`define RASTER_DATA_WID 32
|
||||
|
||||
/* Instead of using parameters, these values are preprocessor
|
||||
* defines so that they may be reference in kernel code.
|
||||
*/
|
||||
`define SAMPLEWID 16
|
||||
`define DAC_DATA_WID 20
|
||||
`define DAC_WID 24
|
||||
`define TIMERWID 8
|
||||
`define ADCNUM 9
|
||||
`define MAX_ADC_DATA_WID 24
|
||||
|
|
|
@ -1,25 +1,57 @@
|
|||
#include <memory>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <verilated.h>
|
||||
|
||||
#include "ram_shim_cmds.h"
|
||||
#include "raster_cmds.h"
|
||||
#include "Vraster_sim.h"
|
||||
using ModType = Vraster_sim;
|
||||
ModType *mod;
|
||||
|
||||
uint32_t main_time = 0;
|
||||
|
||||
double sc_time_stamp() {
|
||||
return main_time;
|
||||
}
|
||||
|
||||
static void _assert(const char *file, int line, const char *exp, bool ev, const char *fmt, ...) {
|
||||
if (!ev) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "%s:%d: assertion failed: %s\n", file, line, exp);
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define STRINGIFY(s) #s
|
||||
/* ,##__VA_ARGS__ is a GNU C extension */
|
||||
#define my_assert(e, fmt, ...) _assert(__FILE__, __LINE__, STRINGIFY(e), (e), fmt ,##__VA_ARGS__)
|
||||
|
||||
static void run_clock() {
|
||||
#ifdef BAILOUT
|
||||
static int iters = 0;
|
||||
#endif
|
||||
for (int i = 0; i < 2; i++) {
|
||||
mod->clk = !mod->clk;
|
||||
mod->eval();
|
||||
main_time++;
|
||||
#ifdef BAILOUT
|
||||
iters++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BAILOUT
|
||||
if (iters >= 1000000)
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cleanup_exit() {
|
||||
|
@ -33,76 +65,171 @@ static void init(int argc, char **argv) {
|
|||
mod = new ModType;
|
||||
mod->clk = 0;
|
||||
atexit(cleanup_exit);
|
||||
|
||||
char *seed = getenv("RANDOM_SEED");
|
||||
if (seed) {
|
||||
unsigned long i = strtoul(seed, NULL, 10);
|
||||
srand((unsigned int)i);
|
||||
}
|
||||
}
|
||||
|
||||
using V = uint32_t;
|
||||
|
||||
// Verilator makes all ports unsigned, even when marked as signed in
|
||||
// Verilog.
|
||||
V sign_extend(V x, unsigned len, bool is_signed) {
|
||||
if (!is_signed)
|
||||
return x;
|
||||
// if high bit is 1
|
||||
if (x >> (len - 1) & 1) {
|
||||
// This mask selects all bits below the highest bit.
|
||||
// By inverting it, it selects the highest bit, and all
|
||||
// higher bits that must be sign extended.
|
||||
V mask = (1 << len) - 1;
|
||||
// Set all high bits to 1. The mask has all bits lower
|
||||
// than the highest bit 0, so the bits in "x" pass through.
|
||||
return ~mask | x;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t read_raster_reg(int reg, unsigned siz, bool is_signed) {
|
||||
mod->kernel_cmd = reg;
|
||||
mod->kernel_ready = 1;
|
||||
while (!mod->kernel_finished)
|
||||
run_clock();
|
||||
mod->kernel_ready = 0;
|
||||
run_clock();
|
||||
|
||||
return sign_extend(mod->kernel_data_out, siz, is_signed);
|
||||
}
|
||||
|
||||
static int32_t write_raster_reg(int reg, unsigned siz, int32_t val, bool is_signed) {
|
||||
int32_t oldval = read_raster_reg(reg, siz, is_signed);
|
||||
|
||||
mod->kernel_cmd = reg | RASTER_WRITE_BIT;
|
||||
mod->kernel_data_in = val;
|
||||
|
||||
mod->kernel_ready = 1;
|
||||
while (!mod->kernel_finished)
|
||||
run_clock();
|
||||
mod->kernel_ready = 0;
|
||||
run_clock();
|
||||
|
||||
int32_t cval = read_raster_reg(reg, siz, is_signed);
|
||||
my_assert(cval == val, "written value (%x) != read val (%x)\n", val, cval);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
static void write_shim_cmd(unsigned cmd, uint32_t val) {
|
||||
mod->shim_cmd = cmd;
|
||||
mod->shim_cmd_data = val;
|
||||
mod->shim_cmd_active = 1;
|
||||
|
||||
while (!mod->shim_cmd_finished)
|
||||
run_clock();
|
||||
mod->shim_cmd_active = 0;
|
||||
run_clock();
|
||||
}
|
||||
|
||||
static void read_shim_ptr() {
|
||||
mod->shim_cmd = RAM_SHIM_READ_PTR;
|
||||
mod->shim_cmd_active = 1;
|
||||
|
||||
while (!mod->shim_cmd_finished)
|
||||
run_clock();
|
||||
mod->shim_cmd_active = 0;
|
||||
run_clock();
|
||||
}
|
||||
|
||||
#define SAMPLES_PER_LINE 16
|
||||
#define NUM_OF_LINES 16
|
||||
static size_t expected_store_index = 0;
|
||||
|
||||
static void init_values() {
|
||||
mod->arm = 0;
|
||||
mod->max_samples_in = 512;
|
||||
mod->max_lines_in = 512;
|
||||
/* Settle time is 1 μs */
|
||||
mod->settle_time_in = 100;
|
||||
|
||||
mod->dx_in = 17;
|
||||
mod->dy_in = 13;
|
||||
mod->coord_dac[0] = 0;
|
||||
mod->coord_dac[1] = 0;
|
||||
|
||||
for (int i = 0; i < ADCNUM; i++)
|
||||
mod->adc_data[i] = 0;
|
||||
mod->adc_finished = 0;
|
||||
mod->adc_used_in = 0;
|
||||
|
||||
mod->ram_valid = 0;
|
||||
|
||||
my_assert(write_raster_reg(RASTER_MAX_SAMPLES, SAMPLEWID, SAMPLES_PER_LINE, false) == 0, "samples per line was not zero");
|
||||
my_assert(write_raster_reg(RASTER_MAX_LINES, SAMPLEWID, NUM_OF_LINES, false) == 0, "max lines was not zero");
|
||||
my_assert(write_raster_reg(RASTER_SETTLE_TIME, TIMERWID, 30, false) == 0, "settle time was not zero");
|
||||
my_assert(write_raster_reg(RASTER_DX, DAC_DATA_WID, 12, true) == 0, "dx was not zero");
|
||||
my_assert(write_raster_reg(RASTER_DY, DAC_DATA_WID, 12, true) == 0, "dy was not zero");
|
||||
my_assert(write_raster_reg(RASTER_USED_ADCS, ADCNUM, 0b111101011, false) == 0, "adcnum was not zero");
|
||||
expected_store_index = SAMPLES_PER_LINE * NUM_OF_LINES * 7 * 2;
|
||||
|
||||
write_shim_cmd(RAM_SHIM_WRITE_LOC, 0x10000);
|
||||
write_shim_cmd(RAM_SHIM_WRITE_LEN, 0x0FFFF);
|
||||
}
|
||||
|
||||
uint32_t *measured_values[ADCNUM];
|
||||
|
||||
static void init_measurements() {
|
||||
std::default_random_engine generator{};
|
||||
std::normal_distribution<> dist{10000, 100};
|
||||
std::random_device rd;
|
||||
|
||||
for (int i = 0; i < ADCNUM; i++) {
|
||||
generator.seed(rd());
|
||||
measured_values[i] = new int32_t[mod->max_lines_in][mod->max_samples_in];
|
||||
for (int j = 0; j < mod->max_lines_in; j++) {
|
||||
for (int k = 0; k < mod->max_samples_in; k++) {
|
||||
measured_values[i][j][k] = dist(generator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit_measurement() {
|
||||
for (int i = 0; i < ADCNUM; i++) {
|
||||
delete measured_values[i];
|
||||
}
|
||||
}
|
||||
|
||||
static std::array<uint16_t, 1 << MAX_BYTE_WID> fifo;
|
||||
static uint32_t read_pos, write_pos;
|
||||
// Forward and reverse, so multiply by 2
|
||||
static std::array<int32_t, SAMPLES_PER_LINE * NUM_OF_LINES * ADCNUM*2> stored_values;
|
||||
static size_t store_index = 0;
|
||||
static std::array<uint16_t, SAMPLES_PER_LINE * NUM_OF_LINES * ADCNUM*2*2> received_values;
|
||||
static size_t pushed_index = 0;
|
||||
|
||||
static void handle_ram() {
|
||||
if (mod->ram_write && !mod->ram_valid) {
|
||||
my_assert(pushed_index < received_values.max_size(), "pushed_index (%zu) maxed out", pushed_index);
|
||||
received_values[pushed_index++] = mod->word;
|
||||
mod->ram_valid = 1;
|
||||
} else if (!mod->ram_write) {
|
||||
mod->ram_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_adc() {
|
||||
static int cntr[ADCNUM] = {0};
|
||||
static bool measuring[ADCNUM] = {0};
|
||||
uint32_t tmp_adc_arm = mod->adc_arm;
|
||||
int i = 0;
|
||||
static int amount_called = 0;
|
||||
|
||||
for (int i = 0; i < ADCNUM; i++) {
|
||||
if (mod->adc_used_in & 1) {
|
||||
if (mod->adc_arm && mod->adc_arm != mod->adc_finished) {
|
||||
while (tmp_adc_arm) {
|
||||
if (tmp_adc_arm & 1) {
|
||||
my_assert(store_index < stored_values.max_size(),
|
||||
"%d = %zu", store_index, stored_values.max_size());
|
||||
uint32_t x = sign_extend(rand(), 24, false);
|
||||
memcpy(&stored_values[store_index], &x, sizeof(x));
|
||||
mod->adc_data[i] = stored_values[store_index];
|
||||
store_index++;
|
||||
}
|
||||
|
||||
i++;
|
||||
tmp_adc_arm >>= 1;
|
||||
}
|
||||
mod->adc_finished = mod->adc_arm;
|
||||
fprintf(stderr, "amount called: %d\n", ++amount_called);
|
||||
} else if (!mod->adc_arm) {
|
||||
mod->adc_finished = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
init(argc, argv);
|
||||
init_values();
|
||||
init_measurements();
|
||||
run_clock();
|
||||
|
||||
mod->arm = 1;
|
||||
while (!mod->finished) {
|
||||
write_raster_reg(RASTER_ARM, 1, 1, false);
|
||||
|
||||
while (mod->is_running) {
|
||||
run_clock();
|
||||
handle_ram();
|
||||
handle_adc();
|
||||
}
|
||||
|
||||
my_assert(pushed_index % 2 == 0, "uneven pushed index %d", pushed_index);
|
||||
my_assert(store_index != pushed_index/2, "store_index (%d) != pushed_index/2(%d)\n", store_index, pushed_index/2);
|
||||
my_assert(store_index == expected_store_index, "store_index (%zu) != (%zu)", store_index, expected_store_index);
|
||||
exit(0);
|
||||
|
||||
for (size_t i = 0; i < pushed_index; i += 2) {
|
||||
int32_t calcval = received_values[i+1] << 16 | received_values[i];
|
||||
my_assert(calcval == stored_values[i/2], "calcval = %x, stored_values = %x", calcval, stored_values[i/2]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2,23 +2,17 @@
|
|||
`include "raster_cmds.vh"
|
||||
`include "ram_shim_cmds.vh"
|
||||
module raster_sim #(
|
||||
parameter SAMPLEWID = 9,
|
||||
parameter DAC_DATA_WID = 20,
|
||||
parameter DAC_WID = 24,
|
||||
parameter DAC_WAIT_BETWEEN_CMD = 10,
|
||||
parameter TIMER_WID = 4,
|
||||
parameter STEPWID = 16,
|
||||
parameter ADCNUM = 9,
|
||||
parameter MAX_ADC_DATA_WID = 24,
|
||||
|
||||
parameter DAT_WID = 24,
|
||||
parameter RAM_WORD = 16,
|
||||
parameter RAM_WID = 32,
|
||||
|
||||
parameter RAM_SIM_WAIT_TIME = 54,
|
||||
parameter RAM_SIM_WAIT_TIME = 72,
|
||||
parameter ADC_SIM_WAIT_TIME = 54
|
||||
) (
|
||||
input clk,
|
||||
output is_running,
|
||||
|
||||
input [`RASTER_CMD_WID-1:0] kernel_cmd,
|
||||
input [`RASTER_DATA_WID-1:0] kernel_data_in,
|
||||
|
@ -26,12 +20,12 @@ module raster_sim #(
|
|||
input kernel_ready,
|
||||
output kernel_finished,
|
||||
|
||||
output [DAC_DATA_WID-1:0] x_dac,
|
||||
output [DAC_DATA_WID-1:0] y_dac,
|
||||
output [`DAC_DATA_WID-1:0] x_dac,
|
||||
output [`DAC_DATA_WID-1:0] y_dac,
|
||||
|
||||
output reg [ADCNUM-1:0] adc_arm,
|
||||
input [MAX_ADC_DATA_WID-1:0] adc_data [ADCNUM-1:0],
|
||||
input [ADCNUM-1:0] adc_finished,
|
||||
output reg [`ADCNUM-1:0] adc_arm,
|
||||
input [`MAX_ADC_DATA_WID-1:0] adc_data [`ADCNUM-1:0],
|
||||
input [`ADCNUM-1:0] adc_finished,
|
||||
|
||||
/* DMA interface */
|
||||
output [RAM_WORD-1:0] word,
|
||||
|
@ -51,13 +45,15 @@ module raster_sim #(
|
|||
* The code to handle each axis (X and Y) are similar.
|
||||
****/
|
||||
|
||||
reg [DAC_WID-1:0] coord_write_buf [1:0];
|
||||
reg [DAC_WID-1:0] coord_to_dac [1:0];
|
||||
reg [DAC_WID-1:0] coord_from_dac [1:0];
|
||||
reg [`DAC_WID-1:0] coord_write_buf [1:0];
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
reg [`DAC_WID-1:0] coord_to_dac [1:0];
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
reg [`DAC_WID-1:0] coord_from_dac [1:0];
|
||||
wire coord_arm [1:0];
|
||||
reg coord_finished [1:0];
|
||||
|
||||
reg [DAC_DATA_WID-1:0] coord_dac [1:0];
|
||||
reg [`DAC_DATA_WID-1:0] coord_dac [1:0];
|
||||
assign x_dac = coord_dac[0];
|
||||
assign y_dac = coord_dac[1];
|
||||
|
||||
|
@ -75,13 +71,13 @@ generate for (ci = 0; ci < 2; ci = ci + 1) begin
|
|||
coord_to_dac[ci] <= coord_write_buf[ci];
|
||||
coord_finished[ci] <= 1;
|
||||
|
||||
case (coord_from_dac[ci][DAC_WID-1:DAC_WID-4])
|
||||
case (coord_from_dac[ci][`DAC_WID-1:`DAC_DATA_WID])
|
||||
4'b1001: begin
|
||||
coord_write_buf[ci] <= {4'b1001, coord_dac[ci]};
|
||||
end
|
||||
4'b0001: begin
|
||||
coord_write_buf[ci] <= 0;
|
||||
coord_dac[ci] <= coord_from_dac[ci][DAC_WID-4-1:0];
|
||||
coord_dac[ci] <= coord_from_dac[ci][`DAC_DATA_WID-1:0];
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
|
@ -98,7 +94,7 @@ end endgenerate
|
|||
* simulator so the C++ code doesn't have to implement timers manually.
|
||||
****/
|
||||
|
||||
wire [ADCNUM-1:0] adc_arm_internal;
|
||||
wire [`ADCNUM-1:0] adc_arm_internal;
|
||||
reg [31:0] adc_wait_cntr = 0;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
|
@ -110,6 +106,7 @@ always @ (posedge clk) begin
|
|||
end
|
||||
end else begin
|
||||
adc_wait_cntr <= 0;
|
||||
adc_arm <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -121,6 +118,7 @@ reg [31:0] ram_wait_cntr = 0;
|
|||
always @ (posedge clk) begin
|
||||
if (!ram_write_internal) begin
|
||||
ram_wait_cntr <= 0;
|
||||
ram_write <= 0;
|
||||
end else if (ram_wait_cntr < RAM_SIM_WAIT_TIME) begin
|
||||
ram_wait_cntr <= ram_wait_cntr + 1;
|
||||
end else begin
|
||||
|
@ -128,7 +126,7 @@ always @ (posedge clk) begin
|
|||
end
|
||||
end
|
||||
|
||||
wire [MAX_ADC_DATA_WID-1:0] ram_data;
|
||||
wire [`MAX_ADC_DATA_WID-1:0] ram_data;
|
||||
wire ram_commit;
|
||||
wire ram_finished;
|
||||
|
||||
|
@ -155,23 +153,18 @@ ram_shim #(
|
|||
);
|
||||
|
||||
/* Converting array to vector, arrays are easier to handle in Verilator. */
|
||||
wire [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data_internal;
|
||||
wire [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data_internal;
|
||||
genvar ii;
|
||||
generate for (ii = 0; ii < ADCNUM; ii = ii + 1) begin
|
||||
assign adc_data_internal[(ii+1)*MAX_ADC_DATA_WID-1:ii*MAX_ADC_DATA_WID]
|
||||
generate for (ii = 0; ii < `ADCNUM; ii = ii + 1) begin
|
||||
assign adc_data_internal[(ii+1)*`MAX_ADC_DATA_WID-1:ii*`MAX_ADC_DATA_WID]
|
||||
= adc_data[ii];
|
||||
end endgenerate
|
||||
|
||||
raster #(
|
||||
.SAMPLEWID(SAMPLEWID),
|
||||
.DAC_DATA_WID(DAC_DATA_WID),
|
||||
.DAC_WID(DAC_WID),
|
||||
.DAC_WAIT_BETWEEN_CMD(DAC_WAIT_BETWEEN_CMD),
|
||||
.TIMER_WID(TIMER_WID),
|
||||
.STEPWID(STEPWID),
|
||||
.MAX_ADC_DATA_WID(MAX_ADC_DATA_WID)
|
||||
.DAC_WAIT_BETWEEN_CMD(DAC_WAIT_BETWEEN_CMD)
|
||||
) raster (
|
||||
.clk(clk),
|
||||
.is_running(is_running),
|
||||
|
||||
.kernel_cmd(kernel_cmd),
|
||||
.kernel_data_in(kernel_data_in),
|
||||
|
@ -198,5 +191,10 @@ raster #(
|
|||
.mem_finished(ram_finished)
|
||||
);
|
||||
|
||||
initial begin
|
||||
$dumpfile("raster.fst");
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
endmodule
|
||||
`undefineall
|
||||
|
|
Loading…
Reference in New Issue