upsilon/firmware/rtl/raster/raster.v

308 lines
7.7 KiB
Coq
Raw Normal View History

2022-10-17 00:44:30 -04:00
module raster #(
parameter SAMPLEWID = 9,
parameter DAC_DATA_WID = 20,
parameter DAC_WID = 24,
2022-11-24 00:50:21 -05:00
parameter DAC_WAIT_BETWEEN_CMD = 10,
parameter TIMER_WID = 4,
2022-10-17 00:44:30 -04:00
parameter STEPWID = 16,
2022-11-26 11:47:06 -05:00
parameter ADCNUM = 9,
2022-10-17 00:44:30 -04:00
parameter MAX_ADC_DATA_WID = 24
) (
input clk,
input arm,
2022-11-26 11:47:06 -05:00
output reg finished,
2022-11-24 00:50:21 -05:00
output reg running,
2022-10-17 00:44:30 -04:00
/* Amount of samples in one line (forward) */
2022-11-24 00:50:21 -05:00
input [SAMPLEWID-1:0] max_samples_in,
2022-10-17 00:44:30 -04:00
/* Amount of lines in the output. */
2022-11-24 00:50:21 -05:00
input [SAMPLEWID-1:0] max_lines_in,
/* Wait time after each step. */
2022-11-26 11:47:06 -05:00
input [TIMER_WID-1:0] settle_time_in,
2022-10-17 00:44:30 -04:00
2022-11-24 00:50:21 -05:00
/* Each step goes (x,y) -> (x + dx, y + dy) forward for each line of
2022-10-17 00:44:30 -04:00
* the output. */
2022-11-24 00:50:21 -05:00
input signed [DAC_DATA_WID-1:0] dx_in,
input signed [DAC_DATA_WID-1:0] dy_in,
2022-10-17 00:44:30 -04:00
/* X and Y DAC piezos */
2022-11-24 00:50:21 -05:00
output x_arm,
2022-11-26 11:47:06 -05:00
output [DAC_WID-1:0] x_to_dac,
/* verilator lint_off UNUSED */
input [DAC_WID-1:0] x_from_dac,
input x_finished,
2022-10-17 00:44:30 -04:00
2022-11-24 00:50:21 -05:00
output y_arm,
2022-11-26 11:47:06 -05:00
output [DAC_WID-1:0] y_to_dac,
/* verilator lint_off UNUSED */
input [DAC_WID-1:0] y_from_dac,
input y_finished,
2022-10-17 00:44:30 -04:00
/* Connections to all possible ADCs. These are connected to SPI masters
* and they will automatically extend ADC value lengths to their highest
* values. */
2022-11-24 00:50:21 -05:00
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,
2022-10-17 00:44:30 -04:00
/* Bitmap for which ADCs are used. */
2022-11-24 00:50:21 -05:00
input [ADCNUM-1:0] adc_used_in,
2022-10-17 00:44:30 -04:00
2022-11-24 00:50:21 -05:00
/* 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 mem_commit,
input mem_finished
2022-10-17 00:44:30 -04:00
);
2022-11-24 00:50:21 -05:00
/* During a scan, some of the ADCs will be scanned, but some will not.
* The data are packed in such a way so that the most significant
* word will contain the highest enabled ADC number, and the least
* significant word will contain the lowest enabled ADC number (and so
* on in between).
*
* There's not a good way to precalculate this so instead the check
* is done at each "send" stage.
*/
2022-10-17 00:44:30 -04:00
/* State machine:
WAIT ON ARM
(arm -> 1)
2022-11-24 00:50:21 -05:00
REQUEST DAC VALUES
(when x and y values are requested)
OBTAIN DAC VALUES
(when x and y values are measured)
2022-10-17 00:44:30 -04:00
LOOP FORWARD WITHOUT MEASUREMENT
(when enough steps are taken)
GET ADC VALUES
(when all ADC values are obtained)
SEND THROUGH FIFO
(when finished)
(when at the end of a line)
LOOP BACKWARD WITHOUT MEASUREMENT
(when enough steps are taken)
GET ADC VALUES, BACKWARDS MEASUREMENT
(when all ADC values are obtained)
SEND THROUGH FIFO, BACKWARDS MEASUREMENT
(when finished)
(when the image is finished)
WAIT FOR ARM DEASSERT
(when arm = 0)
*/
localparam WAIT_ON_ARM = 0;
localparam GET_DAC_VALUES = 1;
2022-11-24 00:50:21 -05:00
localparam REQUEST_DAC_VALUES = 2;
localparam MEASURE = 3;
localparam SCAN_ADC_VALUES = 4;
localparam SEND_VALUE = 5;
localparam ADVANCE_DAC_WRITE = 6;
localparam WAIT_ADVANCE = 7;
localparam ON_ADC_FINISHED = 8;
localparam NEXT_LINE = 9;
localparam WAIT_ON_ARM_DEASSERT = 10;
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;
2022-12-16 19:46:04 -05:00
reg signed [DAC_DATA_WID-1:0] x_val = 0;
reg signed [DAC_DATA_WID-1:0] y_val = 0;
2022-11-24 00:50:21 -05:00
/* 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;
/* 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];
/********** Loop Parameters *************/
2022-11-26 11:47:06 -05:00
reg [ADCNUM-1:0] adc_used = 0;
2022-11-24 00:50:21 -05:00
reg is_reverse = 0;
reg signed [DAC_DATA_WID-1:0] dx = 0;
reg signed [DAC_DATA_WID-1:0] dy = 0;
2022-11-26 11:47:06 -05:00
reg [TIMER_WID-1:0] settle_time = 0;
2022-11-24 00:50:21 -05:00
reg [SAMPLEWID-1:0] max_samples = 0;
reg [SAMPLEWID-1:0] max_lines = 0;
reg [STEPWID-1:0] steps_per_sample = 0;
/* Reading ADC data.
* If this doesn't work, a gigantic vector with large bit shifts
* can also work.
*/
2022-10-17 00:44:30 -04:00
2022-11-24 00:50:21 -05:00
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
end
end endgenerate
2022-10-17 00:44:30 -04:00
always @ (posedge clk) begin
2022-11-24 00:50:21 -05:00
case (state)
WAIT_ON_ARM: begin if (arm) begin
adc_used <= adc_used_in;
dx <= dx_in;
dy <= dy_in;
max_samples <= max_samples_in;
max_lines <= max_lines_in;
2022-11-26 11:47:06 -05:00
settle_time <= settle_time_in;
2022-11-24 00:50:21 -05:00
is_reverse <= 0;
sample <= 0;
line <= 0;
x_to_dac <= {4'b1001, 20'b0};
y_to_dac <= {4'b1001, 20'b0};
x_arm <= 1;
y_arm <= 1;
adc_arm <= 0;
end else begin
running <= 0;
end end
REQUEST_DAC_VALUES: begin
if (x_finished && y_finished) begin
x_to_dac <= 0;
y_to_dac <= 0;
x_arm <= 0;
y_arm <= 0;
2022-11-26 11:47:06 -05:00
state <= GET_DAC_VALUES;
2022-11-24 00:50:21 -05:00
counter <= 0;
end
end
2022-11-26 11:47:06 -05:00
GET_DAC_VALUES: if (counter < DAC_WAIT_BETWEEN_CMD) begin
2022-11-24 00:50:21 -05:00
counter <= counter + 1;
if (!arm) state <= WAIT_ON_ARM;
end else if (!x_arm || !y_arm) 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_arm <= 0;
y_arm <= 0;
counter <= 0;
state <= WAIT_ADVANCE;
end
WAIT_ADVANCE: begin
2022-11-26 12:00:10 -05:00
if (counter < settle_time) begin
2022-11-24 00:50:21 -05:00
if (!arm) state <= WAIT_ON_ARM;
counter <= counter + 1;
end else begin
adc_arm <= adc_used;
adc_used_tmp <= adc_used;
state <= MEASURE;
end
end
MEASURE: begin
if (adc_finished == adc_arm) begin
adc_arm <= 0;
state <= SCAN_ADC_VALUES;
counter <= 0;
end
end
SCAN_ADC_VALUES: begin
if (adc_used_tmp == 0) begin
state <= ON_ADC_FINISHED;
if (sample == max_samples) begin
dx <= ~dx + 1;
dy <= ~dy + 1;
is_reverse <= !is_reverse;
sample <= 0;
if (is_reverse) begin
state <= NEXT_LINE;
end else begin
state <= ADVANCE_DAC_WRITE;
end
end else begin
state <= ADVANCE_DAC_WRITE;
end
end else begin
adc_used_tmp <= adc_used_tmp << 1;
if (adc_used_tmp[ADCNUM-1]) begin
state <= SEND_VALUE;
data <= adc_data_tmp[ADCNUM-1];
mem_commit <= 1;
end
end
end
SEND_VALUE: if (mem_finished) begin
if (!arm) state <= WAIT_ON_ARM;
2022-11-24 11:07:30 -05:00
else state <= SCAN_ADC_VALUES;
2022-11-24 00:50:21 -05:00
end
ADVANCE_DAC_WRITE: begin
if (!x_arm || !y_arm) begin
x_val <= x_val + dx;
y_val <= y_val + dy;
2022-11-26 11:47:06 -05:00
x_to_dac <= {4'b0001, x_val + dx};
y_to_dac <= {4'b0001, y_val + dy};
2022-11-24 00:50:21 -05:00
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
2022-10-17 00:44:30 -04:00
2022-11-24 00:50:21 -05:00
NEXT_LINE: begin
if (!x_arm && !y_arm) begin
if (line == max_lines) begin
state <= WAIT_ON_ARM_DEASSERT;
finished <= 1;
running <= 0;
end else begin
2022-12-16 19:46:04 -05:00
/* rotation of (dx,dy) by 90° -> (dy, -dx) */
x_val <= x_val + dy;
2022-11-26 11:47:06 -05:00
x_to_dac <= {4'b0001, x_val + dx_vert};
2022-11-24 00:50:21 -05:00
x_arm <= 1;
2022-12-16 19:46:04 -05:00
y_val <= y_val - dx;
2022-11-26 11:47:06 -05:00
y_to_dac <= {4'b0001, y_val + dy_vert};
2022-11-24 00:50:21 -05:00
y_arm <= 1;
line <= line + 1;
end
end else if (x_finished && y_finished) begin
counter <= 0;
2022-11-26 11:47:06 -05:00
state <= WAIT_ADVANCE;
2022-11-24 00:50:21 -05:00
x_arm <= 0;
y_arm <= 0;
end
end
2022-11-26 11:47:06 -05:00
2022-11-24 00:50:21 -05:00
WAIT_ON_ARM_DEASSERT: begin
if (!arm) begin
state <= WAIT_ON_ARM;
finished <= 0;
end
end
endcase
2022-10-17 00:44:30 -04:00
end
endmodule