introduce control interface; pack adc_data bits into large vector instead of an array
This commit is contained in:
parent
ac0ed9e2a7
commit
a918d74f05
|
@ -5,6 +5,7 @@
|
||||||
* The kernel then reads these values and sends them to the controller
|
* The kernel then reads these values and sends them to the controller
|
||||||
* over ethernet.
|
* over ethernet.
|
||||||
*/
|
*/
|
||||||
|
`include "raster_cmds.vh"
|
||||||
module raster #(
|
module raster #(
|
||||||
parameter SAMPLEWID = 9,
|
parameter SAMPLEWID = 9,
|
||||||
parameter DAC_DATA_WID = 20,
|
parameter DAC_DATA_WID = 20,
|
||||||
|
@ -16,21 +17,13 @@ module raster #(
|
||||||
parameter MAX_ADC_DATA_WID = 24
|
parameter MAX_ADC_DATA_WID = 24
|
||||||
) (
|
) (
|
||||||
input clk,
|
input clk,
|
||||||
input arm,
|
|
||||||
output reg finished,
|
|
||||||
output reg running,
|
|
||||||
|
|
||||||
/* Amount of samples in one line (forward) */
|
/* Kernel interface. */
|
||||||
input [SAMPLEWID-1:0] max_samples_in,
|
input [`RASTER_CMD_WID-1:0] kernel_cmd,
|
||||||
/* Amount of lines in the output. */
|
input [`RASTER_DATA_WID-1:0] kernel_data_in,
|
||||||
input [SAMPLEWID-1:0] max_lines_in,
|
output reg [`RASTER_DATA_WID-1:0] kernel_data_out,
|
||||||
/* Wait time after each step. */
|
input kernel_ready,
|
||||||
input [TIMER_WID-1:0] settle_time_in,
|
output reg kernel_finished,
|
||||||
|
|
||||||
/* Each step goes (x,y) -> (x + dx, y + dy) forward for each line of
|
|
||||||
* the output. */
|
|
||||||
input signed [DAC_DATA_WID-1:0] dx_in,
|
|
||||||
input signed [DAC_DATA_WID-1:0] dy_in,
|
|
||||||
|
|
||||||
/* X and Y DAC piezos */
|
/* X and Y DAC piezos */
|
||||||
output x_arm,
|
output x_arm,
|
||||||
|
@ -54,9 +47,6 @@ module raster #(
|
||||||
input [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data,
|
input [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data,
|
||||||
input [ADCNUM-1:0] adc_finished,
|
input [ADCNUM-1:0] adc_finished,
|
||||||
|
|
||||||
/* Bitmap for which ADCs are used. */
|
|
||||||
input [ADCNUM-1:0] adc_used_in,
|
|
||||||
|
|
||||||
/* RAM DMA. This is generally not directly connected to the
|
/* RAM DMA. This is generally not directly connected to the
|
||||||
* DMA IP. A shim is used in order to write multiple words
|
* DMA IP. A shim is used in order to write multiple words
|
||||||
* to memory. */
|
* to memory. */
|
||||||
|
@ -114,11 +104,10 @@ localparam GET_DAC_VALUES = 1;
|
||||||
localparam REQUEST_DAC_VALUES = 2;
|
localparam REQUEST_DAC_VALUES = 2;
|
||||||
localparam MEASURE = 3;
|
localparam MEASURE = 3;
|
||||||
localparam SCAN_ADC_VALUES = 4;
|
localparam SCAN_ADC_VALUES = 4;
|
||||||
localparam SEND_VALUE = 5;
|
localparam ADVANCE_DAC_WRITE = 5;
|
||||||
localparam ADVANCE_DAC_WRITE = 6;
|
localparam WAIT_ADVANCE = 6;
|
||||||
localparam WAIT_ADVANCE = 7;
|
localparam NEXT_LINE = 7;
|
||||||
localparam NEXT_LINE = 9;
|
localparam WAIT_ON_ARM_DEASSERT = 8;
|
||||||
localparam WAIT_ON_ARM_DEASSERT = 10;
|
|
||||||
localparam STATE_WID = 4;
|
localparam STATE_WID = 4;
|
||||||
|
|
||||||
/********** Loop State ***********/
|
/********** Loop State ***********/
|
||||||
|
@ -134,26 +123,13 @@ reg signed [DAC_DATA_WID-1:0] y_val = 0;
|
||||||
* which ADC values should be read off.
|
* which ADC values should be read off.
|
||||||
*/
|
*/
|
||||||
reg [ADCNUM-1:0] adc_used_tmp = 0;
|
reg [ADCNUM-1:0] adc_used_tmp = 0;
|
||||||
|
reg [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data_tmp = 0;
|
||||||
/* Buffer to store ADC data. The buffers are permuted in order
|
|
||||||
* for the design to read off the proper values into RAM.
|
|
||||||
*/
|
|
||||||
reg [MAX_ADC_DATA_WID-1:0] adc_data_tmp [ADCNUM-1:0];
|
|
||||||
|
|
||||||
genvar ii;
|
|
||||||
generate for (ii = 0; ii < ADCNUM - 1; ii = ii + 1) begin
|
|
||||||
always @ (posedge clk) begin
|
|
||||||
if (state == SCAN_ADC_VALUES) begin
|
|
||||||
adc_data_tmp[ii] <= adc_data_tmp[ii+1];
|
|
||||||
end else if (state == MEASURE && adc_finished == adc_arm) begin
|
|
||||||
adc_data_tmp[ii] <= adc_data[(ADCNUM-ii)*MAX_ADC_DATA_WID-1:(ADCNUM-ii-1)*MAX_ADC_DATA_WID];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end endgenerate
|
|
||||||
|
|
||||||
/********** Loop Parameters *************/
|
/********** Loop Parameters *************/
|
||||||
reg [ADCNUM-1:0] adc_used = 0;
|
reg [ADCNUM-1:0] adc_used = 0;
|
||||||
reg is_reverse = 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] dx = 0;
|
||||||
reg signed [DAC_DATA_WID-1:0] dy = 0;
|
reg signed [DAC_DATA_WID-1:0] dy = 0;
|
||||||
reg [TIMER_WID-1:0] settle_time = 0;
|
reg [TIMER_WID-1:0] settle_time = 0;
|
||||||
|
@ -162,16 +138,73 @@ reg [SAMPLEWID-1:0] max_samples = 0;
|
||||||
reg [SAMPLEWID-1:0] max_lines = 0;
|
reg [SAMPLEWID-1:0] max_lines = 0;
|
||||||
reg [STEPWID-1:0] steps_per_sample = 0;
|
reg [STEPWID-1:0] steps_per_sample = 0;
|
||||||
|
|
||||||
|
/********** Control Interface ************
|
||||||
|
* This code assumes that RASTER_DATA_WID is greater than all registers.
|
||||||
|
* If a register is equal to the length, omit zero extension.
|
||||||
|
*
|
||||||
|
* This uses a macro since each register is exactly the same code, just
|
||||||
|
* with different length. The arm register is special: it can be adjusted
|
||||||
|
* while the loop is running (in order to terminate the scan), but
|
||||||
|
* otherwise each register can only be modified when the loop is not
|
||||||
|
* running.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Generates code to handle read requests from the kernel.
|
||||||
|
`define generate_register_read(code, width, register) \
|
||||||
|
code: begin \
|
||||||
|
kernel_data_out[(width)-1:0] <= register; \
|
||||||
|
kernel_data_out[`RASTER_DATA_WID-1:(width)] <= 0; \
|
||||||
|
kernel_finished <= 1; \
|
||||||
|
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 \
|
||||||
|
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_ARM, 1, arm)
|
||||||
|
`generate_register_read(`RASTER_RUNNING, 1, running)
|
||||||
|
endcase end
|
||||||
|
end
|
||||||
|
`undef generate_register_read
|
||||||
|
`undef generate_register
|
||||||
|
|
||||||
|
task check_arm();
|
||||||
|
if (!arm) begin
|
||||||
|
state <= WAIT_ON_ARM;
|
||||||
|
running <= 0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
`ifdef VERILATOR
|
||||||
|
task check_deassert_dac_arm();
|
||||||
|
if (x_arm) $error("x_arm asserted");
|
||||||
|
if (y_arm) $error("y_arm asserted");
|
||||||
|
endtask
|
||||||
|
`define CHECK_DAC_ARM check_deassert_dac_arm();
|
||||||
|
`else
|
||||||
|
`define CHECK_DAC_ARM
|
||||||
|
`endif
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
case (state)
|
case (state)
|
||||||
WAIT_ON_ARM: begin if (arm) begin
|
WAIT_ON_ARM: if (arm) begin
|
||||||
adc_used <= adc_used_in;
|
running <= 1;
|
||||||
dx <= dx_in;
|
|
||||||
dy <= dy_in;
|
|
||||||
max_samples <= max_samples_in;
|
|
||||||
max_lines <= max_lines_in;
|
|
||||||
settle_time <= settle_time_in;
|
|
||||||
|
|
||||||
is_reverse <= 0;
|
is_reverse <= 0;
|
||||||
sample <= 0;
|
sample <= 0;
|
||||||
line <= 0;
|
line <= 0;
|
||||||
|
@ -182,22 +215,20 @@ always @ (posedge clk) begin
|
||||||
y_arm <= 1;
|
y_arm <= 1;
|
||||||
|
|
||||||
adc_arm <= 0;
|
adc_arm <= 0;
|
||||||
end else begin
|
state <= REQUEST_DAC_VALUES;
|
||||||
running <= 0;
|
end
|
||||||
end end
|
REQUEST_DAC_VALUES: if (x_finished && y_finished) begin
|
||||||
REQUEST_DAC_VALUES: begin
|
x_to_dac <= 0;
|
||||||
if (x_finished && y_finished) begin
|
y_to_dac <= 0;
|
||||||
x_to_dac <= 0;
|
x_arm <= 0;
|
||||||
y_to_dac <= 0;
|
y_arm <= 0;
|
||||||
x_arm <= 0;
|
state <= GET_DAC_VALUES;
|
||||||
y_arm <= 0;
|
counter <= 0;
|
||||||
state <= GET_DAC_VALUES;
|
|
||||||
counter <= 0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
GET_DAC_VALUES: if (counter < DAC_WAIT_BETWEEN_CMD) begin
|
GET_DAC_VALUES: if (counter < DAC_WAIT_BETWEEN_CMD) begin
|
||||||
|
`CHECK_DAC_ARM
|
||||||
counter <= counter + 1;
|
counter <= counter + 1;
|
||||||
if (!arm) state <= WAIT_ON_ARM;
|
check_arm();
|
||||||
end else if (!x_arm || !y_arm) begin
|
end else if (!x_arm || !y_arm) begin
|
||||||
x_arm <= 1;
|
x_arm <= 1;
|
||||||
y_arm <= 1;
|
y_arm <= 1;
|
||||||
|
@ -211,99 +242,90 @@ always @ (posedge clk) begin
|
||||||
state <= WAIT_ADVANCE;
|
state <= WAIT_ADVANCE;
|
||||||
end
|
end
|
||||||
|
|
||||||
WAIT_ADVANCE: begin
|
WAIT_ADVANCE: if (counter < settle_time) begin
|
||||||
if (counter < settle_time) begin
|
check_arm();
|
||||||
if (!arm) state <= WAIT_ON_ARM;
|
counter <= counter + 1;
|
||||||
counter <= counter + 1;
|
`CHECK_DAC_ARM
|
||||||
end else begin
|
end else begin
|
||||||
adc_arm <= adc_used;
|
`CHECK_DAC_ARM
|
||||||
adc_used_tmp <= adc_used;
|
adc_arm <= adc_used;
|
||||||
state <= MEASURE;
|
adc_used_tmp <= adc_used;
|
||||||
end
|
state <= MEASURE;
|
||||||
end
|
end
|
||||||
MEASURE: begin
|
MEASURE: if (adc_finished == adc_arm) begin
|
||||||
if (adc_finished == adc_arm) begin
|
`CHECK_DAC_ARM
|
||||||
adc_arm <= 0;
|
adc_arm <= 0;
|
||||||
state <= SCAN_ADC_VALUES;
|
adc_data_tmp <= adc_data;
|
||||||
counter <= 0;
|
state <= SCAN_ADC_VALUES;
|
||||||
end
|
counter <= 0;
|
||||||
end
|
end
|
||||||
SCAN_ADC_VALUES: begin
|
SCAN_ADC_VALUES: if (adc_used_tmp == 0 && !mem_commit) begin
|
||||||
if (adc_used_tmp == 0) begin
|
`CHECK_DAC_ARM
|
||||||
if (sample == max_samples) begin
|
if (sample == max_samples) begin
|
||||||
dx <= ~dx + 1;
|
dx <= ~dx + 1;
|
||||||
dy <= ~dy + 1;
|
dy <= ~dy + 1;
|
||||||
is_reverse <= !is_reverse;
|
|
||||||
sample <= 0;
|
|
||||||
|
|
||||||
if (is_reverse) begin
|
if (is_reverse) begin
|
||||||
state <= NEXT_LINE;
|
state <= NEXT_LINE;
|
||||||
end else begin
|
|
||||||
state <= ADVANCE_DAC_WRITE;
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
state <= ADVANCE_DAC_WRITE;
|
state <= ADVANCE_DAC_WRITE;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
is_reverse <= !is_reverse;
|
||||||
|
sample <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
adc_used_tmp <= adc_used_tmp << 1;
|
state <= ADVANCE_DAC_WRITE;
|
||||||
if (adc_used_tmp[ADCNUM-1]) begin
|
end
|
||||||
state <= SEND_VALUE;
|
end else if (mem_finished) begin
|
||||||
data <= adc_data_tmp[ADCNUM-1];
|
`CHECK_DAC_ARM
|
||||||
mem_commit <= 1;
|
state <= SCAN_ADC_VALUES;
|
||||||
end
|
mem_commit <= 0;
|
||||||
|
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];
|
||||||
|
mem_commit <= 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
SEND_VALUE: if (mem_finished) begin
|
ADVANCE_DAC_WRITE: if (!x_arm || !y_arm) begin
|
||||||
if (!arm) state <= WAIT_ON_ARM;
|
x_val <= x_val + dx;
|
||||||
else state <= SCAN_ADC_VALUES;
|
y_val <= y_val + dy;
|
||||||
|
x_to_dac <= {4'b0001, x_val + dx};
|
||||||
|
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;
|
||||||
|
x_arm <= 0;
|
||||||
|
y_arm <= 0;
|
||||||
end
|
end
|
||||||
ADVANCE_DAC_WRITE: begin
|
NEXT_LINE: if (!x_arm || !y_arm) begin
|
||||||
if (!x_arm || !y_arm) begin
|
if (line == max_lines) begin
|
||||||
x_val <= x_val + dx;
|
state <= WAIT_ON_ARM_DEASSERT;
|
||||||
y_val <= y_val + dy;
|
running <= 0;
|
||||||
x_to_dac <= {4'b0001, x_val + dx};
|
end else begin
|
||||||
y_to_dac <= {4'b0001, y_val + dy};
|
/* rotation of (dx,dy) by 90° -> (dy, -dx) */
|
||||||
|
x_val <= x_val + dy;
|
||||||
|
x_to_dac <= {4'b0001, x_val + dy};
|
||||||
x_arm <= 1;
|
x_arm <= 1;
|
||||||
|
y_val <= y_val - dx;
|
||||||
|
y_to_dac <= {4'b0001, y_val - dx};
|
||||||
y_arm <= 1;
|
y_arm <= 1;
|
||||||
sample <= sample + 1;
|
line <= line + 1;
|
||||||
end else if (x_finished && y_finished) begin
|
|
||||||
counter <= 0;
|
|
||||||
state <= WAIT_ADVANCE;
|
|
||||||
x_arm <= 0;
|
|
||||||
y_arm <= 0;
|
|
||||||
end
|
end
|
||||||
|
end else if (x_finished && y_finished) begin
|
||||||
|
counter <= 0;
|
||||||
|
state <= WAIT_ADVANCE;
|
||||||
|
x_arm <= 0;
|
||||||
|
y_arm <= 0;
|
||||||
end
|
end
|
||||||
|
WAIT_ON_ARM_DEASSERT: if (!arm) begin
|
||||||
NEXT_LINE: begin
|
state <= WAIT_ON_ARM;
|
||||||
if (!x_arm && !y_arm) begin
|
|
||||||
if (line == max_lines) begin
|
|
||||||
state <= WAIT_ON_ARM_DEASSERT;
|
|
||||||
finished <= 1;
|
|
||||||
running <= 0;
|
|
||||||
end else begin
|
|
||||||
/* rotation of (dx,dy) by 90° -> (dy, -dx) */
|
|
||||||
x_val <= x_val + dy;
|
|
||||||
x_to_dac <= {4'b0001, x_val + dy};
|
|
||||||
x_arm <= 1;
|
|
||||||
y_val <= y_val - dx;
|
|
||||||
y_to_dac <= {4'b0001, y_val - dx};
|
|
||||||
y_arm <= 1;
|
|
||||||
line <= line + 1;
|
|
||||||
end
|
|
||||||
end else if (x_finished && y_finished) begin
|
|
||||||
counter <= 0;
|
|
||||||
state <= WAIT_ADVANCE;
|
|
||||||
x_arm <= 0;
|
|
||||||
y_arm <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
WAIT_ON_ARM_DEASSERT: begin
|
|
||||||
if (!arm) begin
|
|
||||||
state <= WAIT_ON_ARM;
|
|
||||||
finished <= 0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue