circle.v

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



2007-12-02