module circle_gen(CLK, reset, lock, init, busy, done,
Ax, Ay, Az, Bx, By, Bz, stepsize);
input CLK, reset, lock, init;
wire CLK, reset, lock, init;
output busy, done;
reg busy, done;
output [15:0] Ax, Ay, Az, Bx, By, Bz;
wire [15:0] Ax, Ay, Az, Bx, By, Bz;
reg [15:0] prev_x, prev_y, prev_z;
reg [15:0] next_x, next_y, next_z;
reg [15:0] first_x, first_y, first_z;
assign Ax[15:0] = prev_x;
assign Ay[15:0] = prev_y;
assign Az[15:0] = prev_z;
assign Bx[15:0] = next_x;
assign By[15:0] = next_y;
assign Bz[15:0] = next_z;
input [15:0] stepsize;
wire [15:0] stepsize;
reg [3:0] state;
reg [15:0] d_step;
reg [15:0] cur_step;
parameter done_looping = 4'd0,
looping = 4'd1,
wait_for_init_low = 4'd2,
debug_circle = 1'b0;
wire [8:0] sine_addr;
assign sine_addr[8:0] = cur_step[8:0];
wire [15:0] sine_out;
wire [8:0] cos_addr;
assign cos_addr[8:0] = cur_step[8:0] + 9'd128;
wire [15:0] cos_out;
sineTable9x16bit sineTable(CLK, sine_addr, sine_out);
sineTable9x16bit cosTable(CLK, cos_addr, cos_out);
always @(posedge CLK) begin
if (reset) begin
cur_step <= 16'd0;
prev_x <= 16'd0;
prev_y <= 16'd0;
prev_z <= 16'd0;
next_x <= 16'd0;
next_y <= 16'd0;
next_z <= 16'd0;
busy <= 1'b0;
done <= 1'b0;
state <= done_looping;
if (debug_circle) $display("circle_gen: being reset");
end
else if (lock) begin
case (state)
done_looping: begin
if (init == 1'b1) begin
// start querying the sine table now
cur_step <= stepsize;
// delta step. 1, 2, 3, ...
d_step <= stepsize;
// not busy yet (no valid results out)
busy <= 1'b0;
// not done yet
done <= 1'b0;
state <= looping;
end // if (init == 1'b1)
else begin
busy <= 1'b0;
done <= 1'b0;
end
end
looping: begin
if (cur_step > 512) begin
// not done yet.
busy <= 1'b1;
done <= 1'b0;
// advance prev_[xyz]
prev_x[15:0] <= next_x[15:0];
prev_y[15:0] <= next_y[15:0];
prev_z[15:0] <= next_z[15:0];
// set next_[xyz] to 0
next_x[15:0] <= first_x[15:0];
next_y <= 16'd0;
next_z <= 16'd0;
state <= wait_for_init_low;
end
else begin
// initial case
prev_x[15:0] <= next_x[15:0];
prev_y[15:0] <= next_y[15:0];
prev_z[15:0] <= next_z[15:0];
next_x[15:0] <= cos_out[15:0];
next_y[15:0] <= sine_out[15:0];
next_z[15:0] <= 16'd0;
// turn busy on after the first line. don't draw center
if (cur_step != stepsize) begin
busy <= 1'b1;
end
else if (cur_step == stepsize) begin
// save the first point so we can complete circle in the end
first_x[15:0] <= cos_out[15:0];
first_y[15:0] <= sine_out[15:0];
first_z[15:0] <= 16'd0;
end
// not done
done <= 1'b0;
// advance
cur_step <= cur_step + d_step;
end // else: !if(cur_step > 512)
end // case: looping
wait_for_init_low: begin
// now we're done
busy <= 1'b0;
done <= 1'b1;
if (~init) begin
state <= done_looping;
end
end
endcase // case (state)
end
end // always @ (posedge CLK)
endmodule // circle_gen